Asked by mashtine
on 27 Nov 2014

Hello,

I have the following code to plot my observed readings versus my modelled readings and the code works fine but does not clearly show regions where my modelled data is greater than observed data.

% Create figure

figure1 = figure;

XData = mod1_2001_2014(x,1)';

YData1 = mod1_2001_2014(x,5)';

YData2 = mod1_2001_2014(x,4)';

% Plot with fill

X = [XData fliplr(XData)];

Y = [YData1 fliplr(YData2)];

fill(X,Y,[0.678431391716003 0.921568632125854 1]);

ylim([0 max(YData2)+3])

I was wondering if there is a way to have this so that when the YData2 > YData1 the fill is red and when YData1 > YData2, the fill is the colour it is now.

Any ideas? Thank you!

Answer by Thorsten
on 27 Nov 2014

Edited by Thorsten
on 5 Feb 2015

Accepted Answer

or my solution that does need no interpolation but computes the intersection points.

function fillline(x, y1, y2, col1, col2)

% Thorsten Hansen 2015-05-02 2014-11-27

% See also

% http://www.mathworks.com/matlabcentral/fileexchange/34876--greater-than--fill

if nargin < 3

x = -10:10;

y1 = sin(x);

y2 = cos(x);

end

if nargin < 5

col1 = [1 0 0];

col2 = [0 0 1];

end

hold on

colpatch(y1 >= y2, col1, x, y1, y2)

colpatch(y2 >= y1, col2, x, y1, y2)

plot(x, y1, '-', 'Color', col1)

plot(x, y2, '-', 'Color', col2)

hold off

function colpatch(ind, col, x, y1, y2)

% special case 1: all values of y2 below y1: nothing to fill

if ~any(ind)

return

end

% define fill color as a lighter version of the color on the line above

col = lighten(col);

% force row vectors for proper concatenation in fill below

x = x(:)'; y1 = y1(:)'; y2 = y2(:)'; ind = ind(:)';

% special case 2: no intersections, all values of y2 above y1

if all(ind)

fill([x x(end) fliplr(x) x(1)], ...

[y1 y1(end) fliplr(y2) y2(1)], col, 'EdgeColor', col);

return

end

% general case: y1 and y2 intersect

val = cumsum(diff([0 ind]) == 1).*ind;

v = 1;

ind = find(val == v);

while ~isempty(ind)

xi = x(ind); y1i = y1(ind); y2i = y2(ind);

% determine intersections to fill area between intersections

% determine left intercept

ii = ind(1);

if ii > 1

line1 = [x(ii) y1(ii); x(ii-1) y1(ii-1)];

line2 = [x(ii) y2(ii); x(ii-1) y2(ii-1)];

[xis_left yis_left] = lineintercept(line1, line2);

else

xis_left = [];

yis_left = [];

end

% determine right intercept

ii = ind(end);

if ii < numel(x)

line1 = [x(ii) y1(ii); x(ii+1) y1(ii+1)];

line2 = [x(ii) y2(ii); x(ii+1) y2(ii+1)];

[xis_right yis_right] = lineintercept(line1, line2);

else

xis_right = [];

yis_right = [];

end

% add patch

fill([xis_left xi xis_right fliplr(xi)], ...

[yis_left y1i yis_right fliplr(y2i)], col, 'EdgeColor', col);

%set(h), pause

v = v + 1; % next patch

ind = find(val == v); % indices of next patch

end

function [xis yis] = lineintercept(line1, line2)

slope = @(line) (line(2,2) - line(1,2))/(line(2,1) - line(1,1));

m1 = slope(line1);

m2 = slope(line2);

intercept = @(line,m) line(1,2) - m*line(1,1);

b1 = intercept(line1,m1);

b2 = intercept(line2,m2);

% intersection

xis = (b2-b1)/(m1-m2);

yis = m1*xis + b1;

%plot(xis,yis,'ko','MarkerSize',10)

function col = lighten(col)

col = col + 0.8*([1 1 1] - col);

mashtine
on 4 Feb 2015

Hi Thorsten,

Thanks again for this! Ran into another issue. When I reach to row 155 of my testdata (attached) the code goes wonky and I think it has to do with when y2 is greater than y1. It does not seem to be doing the switch even with both versions above. Unfortunately I am not too familiar with the colpatch function to figure it out myself.

Thorsten
on 5 Feb 2015

Hi Masao,

I missed to also force "ind" to be a row vector. Please find the updated fillline function above. Hope this works now smoothly for everything :-)

Best,

Thorsten

mashtine
on 9 Feb 2015

Thank you!

Sign in to comment.

Answer by Luuk van Oosten
on 27 Nov 2014

Dear Massao,

I do not know exactly how your data looks like, but you could use somthing like:

for i=1:lenght(yourdataset)

if YData1 < YData2 % Let matlab check if Ydata2 is larger than YData1

scatter( x(i,1), y(i,5), 15, [1 0 0], 'filled') hold on;

else % if this condition is not matched, then do the following:

scatter( x(i,1), y(i,4),15, [0 0.68 0.92], 'filled') hold on;

end

Have fun!

mashtine
on 27 Nov 2014

Hi Luuk,

Unfortunately this is not what I want. I would like both y plot on one graph as lines with the space between them filled (as with my code above). I just want to adjust it so that regions where YData2 > YData1 the fill is red and when YData1 > YData2, the fill is the colour it is now. Attached is what I currently have but it shows the same colour during times when the lines criss-cross

Luuk van Oosten
on 27 Nov 2014

Oops, excuse me. I'm not very familiar with plotting lines.

nevertheless, if you try something analogous to

if Ydata1 < Ydata2

fill stuff in fancy blue

else

fill stuff in red

I would expect that to work.

mashtine
on 27 Nov 2014

Thanks Luuk but I am not sure how to do that will the flipr function

Sign in to comment.

Opportunities for recent engineering grads.

Apply Today
## 0 Comments

Sign in to comment.