I have a matlab plot that looks like this:
Where the Y values for each of the subplots are stored in single dimensional arrays. What i would like to do is to find an area where the top graph is above a certain height say 0.5. I would also like to highlight the same area in the other graphs as well.
Here is an example of what I am talking about:
The best i have been able to find so far is the function area which will fill an area on the matlab grid. However, if someone could tell me how to make it transparent and also how to fill multiple areas without having to do lots of area commands that would be great.
Otherwise I can identify a group of areas in a struct and use a for loop to plot them. Here is some psuedo code of the way i would do it:
countstruct = 1;
for i = 1:length(yValue)
if (yValue(i) > 1)
outside = [outside, i]
else
areas(countstruct).outside = outside;
countstruct = countstruct + 1;
clear outside;
end
end
Then to plot the areas i would do this:
for i = 1:length(areas)
area(areas(i).outside, ones(length(area), 1)*14, "SomeThingToMakeItTransperant')
end
and i would do this for each of the subplots. Obviously this is quite convoluted so it would be better to have a one liner. Can anyone think of one?
I figured it out, The psuedo code i provided gets the correct regions. You can then do this:
for i = 1:length(areas)
harea = area(areas(i).outside, ones(length(areas(i).outside), 1)*14, 'LineStyle', 'none')
set(harea, 'FaceColor', 'r')
alpha(0.25)
hold on
end
alpha sets the transparency in most area plots. This in combination with the code in the question results in this:
This is pretty cool to plot in matlab.
Related
I have a Matlab plot that contains relatively high amount of different data and hence if i use standard legend representation, i could not figure out which legend color belongs to which curve.
So, is there any way to put legends on each curve? Lets say "BUS7" text should be located on the purple curve (undermost one).
Thanks.
I am trying to do something like this:
The text(x, y, txt) function allows you to add text at a given location on the plot. link.
Looking at your example, it seems that you want to have all the labels on the left-hand side. So, one way to do it would be like this, where I have generated my own dummy data:
leg = {'First Curve', 'Second Curve', 'Third Curve'};
figure;
x = linspace(1,10,100);
for ii = 1:3
y = x + ii*10;
plot(x, y);
hold on
text(x(1), y(1)+2.5, leg{ii});
end
Regretfully, this does not do anything clever with where the label is placed - it is merely placed slightly above the first point of the curve. You can clearly easily move it along the curve, but if you have many curves, like in your case, the labels will likely overlap and you will need to tinker a bit to avoid this.
I am plotting a closed loop poles of a systems using pzmap.m or pzplot.m whichever you prefer. I want to see the movement of poles and zeros as I change a variable depicted by L.
The function does not have a direct handle for color. In the example you can just choose the standard colors but cannot give your own color. Since I have to plot multiple times on the same figure, I create a handle for every iteration in a for loop and use findobj to set the color of the curve. To get the colors I want to have a colorbar. So I use jet to get the color distribution for my graph. But the market size stays the same and I have one ugly looking figure.
MWE:
cb=jet(10);
s=tf('s');
L_array=5:5:50;
figure; hold on;
for i=1:length(L_array)
L=L_array(i);
G=((58.2+11.7*L)*s^2*25^2+(3996.8 + 815.7*L)*s*25+815.7*25^2)/(s^2*(s^2*25^2+126.9*s*25+(3996.8+1.9*25^2)));
CL=feedback(G,1);
pzmap(CL);
h = findobj(gcf,'type','point'); set(h,'markers',12,'color',cb(i,:));
clear L G CL h
end
grid;
c=colorbar
c.Label.String = 'L'
If you run it you'll see that the size doesn't change and graph looks crazy with the y axis on either side labelled with ticks. I want a proper colorbar from blue to red and the colors distributed properly but can't get it after multiple tries. If I can get less cluttering that would be helpful too.
The are several problems in your code
h = findobj(gcf,'type','point'); The things drawn in the screen are actually of type 'line'!
Every iteration, you catch all the points, modify them an dimdediately after delete the properties with clear.
Additionally, h = findobj(gcf,'type','line'); will not return a single thing, but a set of them, so you need to index through it to set the properties. My modified code working looks like this:
clear;clc
cb=parula(10);
s=tf('s');
L_array=5:5:50;
figure; hold on;
for i=1:length(L_array)
L=L_array(i);
G=((58.2+11.7*L)*s^2*25^2+(3996.8 + 815.7*L)*s*25+815.7*25^2)/(s^2*(s^2*25^2+126.9*s*25+(3996.8+1.9*25^2)));
CL=feedback(G,1);
pzmap(CL);
end
% lets do this in the end!
% you will have length(L_array)*2 +1 items in h
h = findobj(gca,'type','line');
for jj=2:length(h)
set(h(jj),'MarkerSize',12,'Color',cb(floor(jj/2),:));
end
grid;
colormap(parula); % I am using parula, you can use jet, but I discourage it
c=colorbar;
PD: there are tons of reasons not to use jet!! Use perceptually uniform colormaps please!
I want to graph different ellipses at different heights (z-coordinates).
My idea was to write the following code:
z=0:1/64:3/8;
t=linspace(-pi,pi,25);
[t,z]=meshgrid(t,z);
x=cos(-t);
y=cos(-t-4*pi*z);
I would like MATLAB to read my code like:
"Find x and y, and plot at the corresponding height (z). By doing so, join the points such that you'll form an ellipse at constant z".
I'm not sure what kind of function I could use here to do this and was hoping for someone to tell me if there exists such a function that will do the job or something similar.
In case you're wondering, I want to graph the polarization of light given two counterpropagating beams.
EDIT: While this is similar to the question draw ellipse and ellipsoid in MATLAB, that question doesn't address plotting 2D ellipses in 3D axes, which is what I am trying to do.
This can be solved by removing the meshgrid, and just using a plain old for-loop.
t = linspace(-pi,pi,25);
z = 0:1/64:3/8
f = figure;
hold on;
for i = 1:length(z)
x=cos(-t); y=cos(-t-4*pi*z(i));
plot3(x,y,z(i)*ones(length(z),1));
end
The problem in the original code is that you're trying build the ellipses all at once, but each ellipse only depends on a single z value, not the entire array of z values.
When I run this code, it produces the following plot:
It's difficult to identify in this area plot each one of the many filled areas by just looking at the legend (it's like 16!).
So, I was wondering if there's a way to place some sort of labels (with a pointer perhaps?) inside the plot that clearly identifies each filled areas?
Thanks!
Here is an alternative using annotation objects and the textarrow option, which displays text along with an arrow. This could be useful to you to point in narrow regions where text would hide data.
For example:
clear
clc
close all
x = 1:128;
%// Plot data
figure
hAxes1 = axes('Position',[.1 .1 .6 .8]);
image(x.');
axis off
colormap(jet(128))
%// Define labels
ColorLabels = {'Red';'Orange';'Green';'Blue';'More blue'};
%// Define starting and ending x and y positions
xstart = .8;
xend = .6;
ystart = linspace(.1,.8,numel(ColorLabels));
yend = linspace(.15,.8,numel(ColorLabels));
for k = 1:numel(ColorLabels)
annotation('textarrow', [xstart xend],[ystart(k) yend(k)],...
'String', ColorLabels{k});
end
gives the following output:
There may be a builtin way that I don't know about but I find the lower-level text function is usually the best answer for this kind of thing.
It'll require some housekeeping - you have to supply an x and y coordinate and the text to print, e.g.
text(20, 400, 'Region 4')
which will centre the label on (20,400) (see the 'VerticalAlignment' and 'HorizontalAlignment' name-value pairs in the docs for fine-tuning), so for me it's usually preferable to write a small wrapper that will work them out from the data. Of course this is usually specific to the particular type of data you're using and rarely generalises to other uses of area plots, but that's most likely why there isn't already a generic labelling function (that I'm aware of).
I have several sets of (x,y) data that I'd like to plot as line plots on the same figure. I have no trouble with matplotlib doing this, but I cannot get the same results with Chaco. Code and output are shown below.
My matplotlib-based code looks like this:
for track in tracks:
xw = np.array(track['xw'])
yw = np.array(track['yw'])
plt.plot(xw, yw, 'b-')
if not plt.gca().yaxis_inverted():
plt.gca().invert_yaxis()
My Chaco-based code looks like this:
for track in tracks:
x = np.array(track['xw'])
y = np.array(track['yw'])
plot = create_line_plot((x,y), color='blue', width=1.0)
plot.origin = 'top left'
container.add(plot)
if track == tracks[0]:
add_default_grids(plot)
add_default_axes(plot)
My matplotlib-based output looks like this:
My chaco-based output looks like this:
The problem with my Chaco-based code above was that I was using an OverlayPlotContainer (container). Because of this, each plot (from create_line_plot) was being drawn with its own axes rather than each plot being drawn on the same set of axes. The following works:
pd = ArrayPlotData()
plot = Plot(pd)
for ii, track in enumerate(tracks):
x = np.array(track['xw'])
y = np.array(track['yw'])
x_key = 'x'+str(ii)
y_key = 'y'+str(ii)
pd.set_data(x_key, x)
pd.set_data(y_key, y)
plot.plot((x_key, y_key), color='blue', origin='top left')
Chaco and Matplotlib are not really trying to address the same types of problems. Matplotlib is better for bringing up a quick plot in a script and is very easy to use. Chaco is a plotting framework that allows:
a stronger architecture for dealing with larger datasets more smoothly
a frameworks that makes it easy to build a GUI around the plot (Traits)
the creation of custom interactive tools on top of plots
Leveraging that framework however requires more code, and the recommeded way to build plots in Chaco is to use its Object Oriented syntax. The simplest but realistic Chaco plot would be something like this. It requires an ArrayPlotData to hold the data and a Plot object to create a plotting area and hold different ways to render that data.
You want to have many line plots instead of just one. You can simply add a for loop inside the __init__ method to add every relevant numpy array inside the ArrayPlotData and for each pair of arrays, to call the plot method of the Plot object (but only 1 Plot object is needed). Something similar is done a little further down in the page.
Good luck,