Calculating area under curve with cutoff

2 views (last 30 days)
Robin Schäfer
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:
  4 Comments
Robin Schäfer
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 =)

Sign in to comment.

Answers (1)

darova
darova on 15 Feb 2020
Edited: darova on 15 Feb 2020
Don't know about vectorizing. Maybe this part will be simpler and faster
load v.mat
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

Categories

Find more on Simulink Functions in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!