Change line colour depending on y axis value

I have a graph with a blue line plotted that passes through a region around y=±2 (grey in the top image).
I want that line to change colour to also be grey only when it passes through this region (mockup in bottom image).
i.e. Above y=2 line is blue, between y=2 & y=-2 line is grey, below y=-2 line is blue. The format of the variable used to plot the line is also shown below.
example_plot.png
example_variable.png
example_plot2.png

 Respuesta aceptada

Adam Danz
Adam Danz el 27 de Ag. de 2019
Editada: Adam Danz el 27 de Ag. de 2019
Since a line object cannot have multiple colors, you'll need to split the the (x,y) coordinates into 2 groups: within and outside the zone. Replace data with NaNs so that those section are not plotted.
Here's a demo
% Produce some curve & plot it
x = 0:1:3000;
gf = @(x, sigma, t, v) v*exp(-(((x-t).^2)/(2*sigma.^2)));
y = gf(x, 200, 1500, 40);
figure()
subplot(2,1,1)
plot(x,y)
title('All data')
% Define a y-axis window and determine which coordinates
% pass through the window
window = [10,20]; % y=10 to y=20
% Find the index of coordinates that are within the window
yInWindowIdx = y > window(1) & y < window(2);
% Plot all of the "out" data
subplot(2,1,2)
title('Segmented data')
hold on
xOut = x;
xOut(yInWindowIdx) = NaN;
yOut = y;
yOut(yInWindowIdx) = NaN;
plot(xOut, yOut, 'b-', 'LineWidth', 3)
% Plot all of the "in" data
xIn = x;
xInt(~yInWindowIdx) = NaN;
yIn = y;
yIn(~yInWindowIdx) = NaN;
plot(xIn, yIn, 'r-', 'LineWidth', 3)

6 comentarios

Matthew
Matthew el 28 de Ag. de 2019
I have got it working as you described, however now because it is two seperate lines, I have lost the interpolation between the data points that I had previously. Is there any way to retain the interpolation (and have it conform to the colour scheme as well)?
example_plot3.png
Adam
Adam el 28 de Ag. de 2019
You can manually interpolate and add new points in that are just either side of the boundary.
Matthew
Matthew el 28 de Ag. de 2019
I will be running this code with multiple data sets and so would prefer to avoid having to manually edit each one before running it. Is there a way to automatically detect where interpolated lines should be drawn and and data points to reflect this?
Well, when I said 'manually', I didn't mean literally manually, I was meaning you put code in that will do the interpolation to create two new points each time the line crosses the boundary rather than relying on the plotting instruction to join the dots. Using e.g.
doc interp1
It's not trivial as you need to work out where your plot crosses the boundary line and interpolate new values at that point, but once you have that the interpolation and insertionof the points is easy.
Matthew
Matthew el 28 de Ag. de 2019
Ok thanks for the help, I'll investigate how to do that.
Adam Danz
Adam Danz el 28 de Ag. de 2019
The data isn't interpolated in the first place. Matlab connects the coordinates with lines but that's no interpolation. I agree with Adam that if you interpolate the data, that will address the problem.
Another solution would be make the first and last point within each "in-zone" segment a shared point such that those bookend points are in both lines. Then the blue like would extend into the "in-zone" until it touches the first in-point.

Iniciar sesión para comentar.

Más respuestas (1)

Stephen23
Stephen23 el 28 de Ag. de 2019
Editada: Stephen23 el 28 de Ag. de 2019
Method one: FEX
Some of these might do what you want:
etc.
Method two: multiple axes
Here is a straightforward method that does not require data interpolation or any data manipulation. It works by simply overlaying a second axes on top of the first, and plotting exactly the same data. Note how the colored lines are "cut off" at the boundaries, even though there are no data points there!
X = (0:0.1:1)*2*pi;
Y = sin(X);
ub = +0.4; % upper bound
lb = -0.3; % lower bound
fgh = figure();
ax1 = axes('parent',fgh); % background
ax2 = axes('parent',fgh); % foreground
plot(ax1,X,Y,'-*','Color',[0,0,1],'LineWidth',2);
plot(ax2,X,Y,'-*','Color',[1,0,0],'LineWidth',2);
ylm = get(ax1,'YLim');
pos = get(ax1,'Position');
pos(2) = pos(4)*((lb-ylm(1))/diff(ylm))+pos(2);
pos(4) = pos(4)*(ub-lb)/diff(ylm);
set(ax2, 'Position',pos, 'Visible','off', 'YLim',[lb,ub])
hold(ax1,'on')
plot(ax1,X([1,end]),[ub,ub],'-') % horizontal line
plot(ax1,X([1,end]),[lb,lb],'-') % horizontal line
Giving:
Using three or four axes would allow complete control over how the lines appear, e.g. if the (dotted) lines "show through" from the backround axes.

Categorías

Más información sobre Line Plots en Centro de ayuda y File Exchange.

Preguntada:

el 27 de Ag. de 2019

Comentada:

el 28 de Ag. de 2019

Community Treasure Hunt

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

Start Hunting!

Translated by