# Calculating area under curve with cutoff

2 views (last 30 days)
Robin Schäfer on 13 Feb 2020
Edited: darova on 15 Feb 2020
Hey Community,
I got a n-by-1 row vector obtained by measured data with n likely beeing about 100.000. The values can be either positive or negative and are derived as the difference from 2 other functions: I calculated the area with cumtrapz / cumsum (red line): The value of the cumulated area under the curve should display a state which can not be negative. Therefore, I want to lift up the curve in the upper graph in the consecutive negativ intervals, so it looks like the blue line. To get there i used this code:
dv=diff(v);
for a=1:length(v)-2
if v(a)<0
if dv(a)>0 && dv(a+1)<=0
v(a:end)=v(a:end)-v(a);
end
v(a)=0;
end
end
This code works for me, but it is not very economic. I would like to avoid the for loop and use a faster vectorized solution because of speed. The function is going to be called about thousand times or even more often with vectors about 100k. Could you help me to find a more convenient way for calculation?
A possible solution could seek for consecutive local minima (tn). Detect the first point following after the local minimum which is equal (pn) and then create a stepwise mixed function which looks similar to this one: Robin Schäfer on 15 Feb 2020
Okay - The for-loop above is doing what I want:
dv=diff(v); % difference to determine local minima
for a=1:length(v)-2
if v(a)<0 % for all negative values: set zero
if dv(a)>0 && dv(a+1)<=0 % detect change of sign for local minimum
v(a:end)=v(a:end)-v(a); % lift up the rest of v to the actual value(v(a))
end
v(a)=0;
end
end
% After the lift up nothing is going to happen until negative values occur again
% note that actual value v(a) has to be negative, otherwise + abs(v(a)) could be used as well
Again: The formula works like intended, but I would like to prefer a vectorized solution for faster computing =)

darova on 15 Feb 2020
Edited: darova on 15 Feb 2020
Don't know about vectorizing. Maybe this part will be simpler and faster
v = cumsum(v);
v1 = v;
dv1 = v*0;
for i = 1:length(v1)-1
if v1(i+1) < dv1(i)
dv1(i+1) = v1(i+1);
else
dv1(i+1) = dv1(i);
end
end 