edit: I figured it out and don't see a place to mark this as answered. Thanks for the suggestions though everyone!
A couple of weeks ago I was trying to force MATLAB to display a y = 0 line for a plot I was making. It was easy enough to search for, but apparently I made it automatic. Now I can't find anything even remotely similar to this new problem. When I run this code:
plot(x,y_known,x,y_simulated);
legend('Simulated','This stupid line right here','Known')
I get the following:
Notice the line at y = 0, it is not in the code. I wouldn't really care, but it is the second line in the figure and it messes up my ability to create a legend. i.e., if the legend entry was just:
legend('Simulated','Known')
then the legend would say that the known value was green, which is certainly not the case.
I don't really want to create a handle for every single line I plot in the future, and would much rather just get rid of this line. Can anyone provide some help, or at least point me in the right direction?
edit: The y = 0 line also changes its line properties based on whatever is supplied to the first plot entry. So plot(x,y1,'--',x,y2); makes both y1 and y = 0 dashed, but plot(x,y1,x,y2,'--'); would just render the second line dashed
As an absolute last resort (after failing to find how the line actually gets there), what you can do is access the Children property of your axes and delete the child which is the line you don't want.
Something along the lines of:
ch = get(gca,'Children');
delete(ch(2)); %// Where 2 should be replaced by the child index you're trying to delete.
There was an errant two much earlier in the code, giving a variable 2 columns instead of one. I didn't realize Matlab would be helpful be helpful and plot both columns (I've always explicitly told it to plot both). Just another case of someone not thinking in vector mode when using Matlab!
Related
I need help to skip lines in the legend of boxplots : I have a plot with two boxplots, and each of them has a legend to long to fit on a single line.
I tried this, X being my matrix of data (two colums) :
boxplot(X,'Labels',{'1stpartofthelegend\newline2ndpartofthelegend','1stpartofthelegend\newline2ndpartofthelegend})
This solution works in other types of plots, like a plotspread plot so I don't understand why it is not working here ?
I found this question, but the solutions are not working for me, maybe because I have a more recent version (R2018b).
I actually want to add my boxplots over a plotpsread plot, but when I do that the legends of the boxplots win over the legends of the plotspread (even if I add boxplots without legends, the previous legends of the plotspread are replaced by "1" and "2"). So preventing the boxplot to erase the previous legend would be a nice solution but as I failed to do that I tried to find another way.
Thank you for your help
You want to set the 'Labels' of the boxplot for multiple lines. So use a cell of cells:
Lbl = { {'1st entry (1st line)','2nd entry (1st line)'},...
{'1st entry (2nd line)','2nd entry (2nd line)'} };
boxplot(rand(100,2),'Labels',Lbl)
EDIT
LaTeX commands work in the title and labels but apparently there is no interpreter or TickLabelInterpreter property for boxplot-Labels:
Error using internal.stats.parseArgs (line 42)
Invalid parameter name: TickLabelInterpreter.
Though there are quite a lot of answered questions to that kind of issue, I wasn’t able to find a proper solution for my exact problem. Anyway.
I try to format my tick lables like shown in the following example:
I already found out that the ‘sprintf’ command is offering a possibility to alter the tick format. The closest I came to what I want is the 'e-notation' triggered by the following command:
set(ax,'YTickLabel',sprintf('%2.0e|',yticks))
However, I’d like my labels to appear just as shown in the example picture. Is there a simple way to do that?
Thank you very much in advance,
Joe
You could use Latex formatting and sprintfc to produce what you want. (You might not need sprintfc at all actually but that's a nice way of creating a cell array of strings with numbers in a single line.):
set(ax,'YTickLabels',sprintfc('10^{%i}',yticks)
In a general example (here with x-axis formatted):
clear
clc
close all
x = 0:100000;
y = log(x);
figure
semilogx(x,y)
xt = get(gca,'XTick');
set(gca,'XTickLabels',sprintfc('10^{%i}',0:numel(xt)-1))
outputs the following:
Am I missing something? Why not use semilogy?
x = -3:0;
y = 10.^x;
semilogy(x, y);
set(gca, 'YMinorGrid', 'on')
I try to remove the Matlab-given units from this plot but I don't find a way:
figure(1)
hold on
set(gcf,'PaperUnits','centimeters',...
'PaperSize',[15 9],...
'PaperPosition',[0 0 15 9]);
pzmap(LB); sgrid; grid on; axis equal;
title('');
xlabel('\sigma [rad/s]')
ylabel('\omega [rad/s]')
hold off
After that commands the xlabel looks like this: \sigma [rad/s] (seconds^-1). The seconds comes with pzmap. How can I remove them?
I found, some strange behavour:
If generate code by the figure plot manager I get this:
% Create xlabel
xlabel('\sigma [rad/s] (seconds^{-1})','Units','pixels');
Why???
Now I get it - without pzmap/pzplot
pol = pole(sys)
figure(1)
plot(real(pol(:)),imag(pol(:)),'x')
title('');
xlabel('\sigma [rad/s]');
ylabel('\omega [rad/s]');
sgrid
pzmap is a high-level convenience function, but it's not the best choice for this (it's also stored in a folder of obsolete functions in R2013a, so it may get marked for official removal in the future). Instead, let's create an example plot using pzplot directly instead of pzmap. This is still a plot function that does a lot under the hood, but it returns a handle, h, to the plot:
sys = rss(3,2,2);
h = pzplot(sys);
sgrid;
axis equal;
We can via the options of a pzplot with getoptions:
p = getoptions(h)
To set the labels and units as you desire, you might try this, using setoptions:
p.Title.String = '';
p.XLabel.String = '\sigma';
p.YLabel.String = '\omega';
setoptions(h,p);
I believe that the units of 'seconds-1' that the plot displays is equivalent to the 'rad/s' that you want to specify. I know that the two look is very different (I prefer being specific about radians myself), but that's a disadvantage of using such a plot function that tries to do everything for you. If you wanted to remove the default string or add another option, you'd likely have to do some low level hacking. An easier way around, might be to use the "Generate Code..." command ("Generate M-File..." in older versions") under the "File" menu in the figure's toolbar and edit the plot labels there (there's also a programmatic option for this on the File Exchange). Or you could output to postscript and edit that.
Alternatively, you can use pzoptions to create a list of options to pass to pzplot or pzmap (undocumented in the latter case):
p = pzoptions;
p.Title.String = '';
p.XLabel.String = '\sigma';
p.YLabel.String = '\omega';
sys = rss(3,2,2);
pzplot(sys,p);
sgrid;
axis equal;
You'll see that that for some reason the text size is much smaller in this case. pzplot and pzmap must set the font size to 10 themselves. You could easily do this.
Fore more on customizing this and related Control toolbox plots, see this article.
After intense low-level digging, there is actually a pretty simple way to override the default behavior.
p = pzplot(sys);
p.AxesGrid.XUnits = 'rad/s';
p.AxesGrid.YUnits = 'rad/s';
Changes appear to take effect immediately. I have even tried setting the value to nothing, i.e.
p.AxesGrid.XUnits = '';
and it effectively removes the annoying parenthesis with the units. Technically, matlab creates a custom-class element they store under the name AxesGrid in the resppack.mpzplot class instance, with some standard LTI-behavior. You can probably work around some stuff by "injecting" a script with the same name as one of the standard library functions, so that it will be called instead, and change things in there, but this is the closest I have come to removing those annoying units in a few lines.
As a side info, the AxesGrid object is initialized in
...\controllib\graphics\#resppack\#pzplot\initialize.m
should you want to check it out.
So I have 3 lines (technically patches) that have some transparency enabled. These lines were generated by the patchline FEX submission. The FEX entry works great by making patches seem like lines by adding a NaN to the end of the data so it doesn't create a big black patch between the end points of my line.
My lines looks like this
__ __
\ /
_ \ / _
\ \__/ /
\______/
The patch extends from the left end point to the right end point in a straight line across the top and then follows the line on the bottom. The actual patch is hidden (not drawn) though so all the user sees is the lines
The problem is if I wanted to click the bottom hump of the top line, it acts like I clicked the bottom line because it is part of that patch.
I have thought of a couple of workarounds and was hoping you guys could point out flaws or add ideas I might have missed with my workarounds.
Workaround #1
Ideally, I would create an actual line (line series obj.) over the transparent lines. I would turn hittest off on the patches and I would make the actual line invisible, but turn hittest on. The problem I am 99% sure exists is that if visibilty is off, you can't click the object. If anybody has a work around to that issue (documented or otherwise), that would be great.
Workaround #2
Turn the patchline hittest property to off. Make mock line objs. that follow the patchline coords. and have a line width very very small so as to make the line ideally pretty much invisible and have hit test clicks point to these lines instead. Has anybody tried something like this before? (I'm at work and can't try it now)
Workaround #3
NOTE THAT I REALLY DONT WANT TO DO THIS It is of course possible to turn off hittest for the patch/line objs and use the axes buttondown to figure out what patch obj (just the line part) it was closest to.
Once again, any insight would be much appreciated either about my possible work arounds, the situation in general, etc.
Thanks, Shaun
The problem can be illustrated with two line-thick patches, one of which is NOT parallel to the axes:
patch([2 8 8],[5 10 10],'w','EdgeColor','b','EdgeAlpha',0.4,'LineWidth',3)
patch([2 8 8],[4 4 4],'w','EdgeColor','r','EdgeAlpha',0.4,'LineWidth',3)
xlim([0 10])
ylim([3 11])
You cannot select but those lines which are parallel to one of the axes.
Workaround #1: impossible.
Workaround #2: quite visible, why would you need transparent lines then?
Workaround #3: the only way...
Workaround alternative: submit to the TMW a technical request to improve clickability of patches.
Oleg, your initial post somehow inspired me to come up with my elegant solution. (Don't ask me how, just accept my "thank you" haha)
The elegant solution to my problem required me to go beyond patch properties and turn to the axes child order. Under the assumption that none of the lines would intersect each other, I was able to plot them in a order where the bottom one was first, then the second lowest, etc. until I got to the top (effectively rearranging child order).
If anybody else stumbles upon this, what you can do (assuming your lines don't intersect) is to sort the first Y (or whatever values) to go from lowest to highest (in this case) in your plot, and make sure your sort function returns the indicies.
I don't have my computer in front of me, but what you end up doing is effectively making an acontinuous for loop, looping through the indicies.
something like:
for i=[6 2 5 4 1 3]
plot(X(:,i),Y(:,i))
end
Where the 6th column was my lowest data, 2nd column was second lowest on plot, etc.
I want to create a vertical bar plot. This is my code:
bar (x, sensiv);
title ('Promedio X')
xlabel('Nm')
ylabel('Refl.')
The problem is it looks like a stair plot. I've tried to add (x,sensiv, 'stacked') but it doesn't work. It looks grouped, as you can see in the next image:
graph http://imageshack.us/a/img689/9449/capturawv.jpg
I think it's because of x-axis but I couldn't change it. How can I do it? Does somebody knows how can I do it?
EDIT
Thanks Colin! I've tried to zoom and I understand what you mean and I've tried with different values, as slayton and you said.
I think that maybe it's the way I've code the plot, it is possible?
abc=0;
for p=(61:201)
abc(p)=out1_c;
end
for p=(151:301)
abc(p)=out2_c;
end
for p=(231:380)
abc(p)=out3_c;
end
for p=(381:596)
abc(p)=out4_c;
end
for p=(1152:1531)
abc(p)=out5_c;
end
for p=(1651:2051)
abc(p)=out7_c;
end
for p=(2052:2151)
abc(p)= 0;
end
The default value for the width of the bars in a bar plot is 0.8, so given that you're not currently specifying the width, you should have gaps in between each bar. This is going to sound really obvious, but have you tried zooming in on the bar plot that is created? For some datasets, the bar function will return a plot that looks like a stair plot, but in fact has gaps if you zoom in far enough. If this is the case, then you should be able to get the gaps you want by tinkering with the width parameter as suggested by slayton.
EDIT
Okay. First things first. If you want to post additional information, you should add it to your question, NOT post it as a new answer! You can do this by clicking the edit button just below where your question is on the page. To make things more readable, you might preface your edit with a capitalized bold-face heading "EDIT" as I have done here. If you are able, try now to move the additional information you've given back into your question, and then delete the answer.
Second, I have to be honest, the additional information you posted was somewhat confusing. However, I think I understand what you want now. You want 7 bars coming up to the heights out1_c, out2_c, ..., out7_c (variable names taken from your additional information) with a small gap between each bar, and the x-axis to reflect (approximately) the intervals 450-550, 550-650, etc.
Well, if you want 7 bars, then you want your input to only have seven elements. Set:
y = [out1_c; out2_c; out3_c; out4_c; out5_c; out6_c; out7_c];
y now gives you the heights your bars will come up to on the y-axis. To locate the bars on the x-axis, define a vector x that also has seven elements, where each element gives the midpoint of where you want the bar to be on the x-axis. For example:
x = [100; 200; 300; 400; 500; 600; 700];
Then just use bar(x, y). This should get you started.
A final point on the code you posted, you can actually completely avoid the loops: read up on vectorization. But if you are going to insist on loops, the first and most important rule is to preallocate your vectors/matrices. In your code abc starts out as a scalar (a 1 by 1 matrix), but then for every p, you are adding an element at index p. What is actually happening in the background is for every p, matlab is scrapping the current abc you have in memory, and building it again from scratch with the additional element. As you might expect, this will slow down your code by many orders of magnitude.
You can set the width of the individual bars by passing a value between 0 and 1 to bar. Passing 1 indicates that there should be no space between the bars
bar(x,y,1)
Passing anything less than 1 will reduce the bar sizes and introduce spacing between the individual bars
bar(x,y,.5)