I have plenty of subplots I have to load and put all together using Matlab. I want to add personalized Ticks but my approach does not seem to work. My mwe is the following:
x = 1:1:1000;
r = rand(1000,1);
my1 = subplot(2,3,1);
my1 = bar(x,sort(r));
title ('This works')
xlabel ('This works too')
xlim ([0 1000])
my = get(gca);
my.XTick = [1 200 499]
And this last point does not work. Why? How can I fix it?
get(gca) returns a struct of all graphics properties of the current axes, not the axes handle itself. Any changes made to this struct of properties are not mirrored in your actual axes. You need to modify the properties of the axes directly using set
set(gca, 'XTick', [1 200 499])
Or if you're on 2014b
% Don't use get(gca) to get the handle
ax = gca;
% Set the XTick property
ax.XTick = [1 200 499];
Related
Please see the following code which creates a 2 by 2 subplot with some plots:
x = linspace(0,2*pi);
y = sin(x);
hfig = figure('Position',[1317 474 760 729]);
subplot(2,2,1)
plot(x,y)
ylabel('plot1');
subplot(2,2,2)
plot(x,y.^2)
ylabel('plot2');
subplot(2,2,3)
plot(x,y.^3)
ylabel('plot3');
subplot(2,2,4)
plot(x,abs(y))
ylabel('plot4');
in each one, I have added labels by hand in Tools: Edit plot (a) (b) (c) (d) producing this figure:
The problem is, if I resize the plot they are no longer aligned with the ylabel text:
Is there a way to add these labels programmatically and have them automatically align to the ylabel text? I am surprised MATLAB does not have something like this built in already.
Thanks
This is not something that is easy to do without attaching a listener to the figure resize event (see example), and doing some computations related to aspect ratios.
It's not entirely clear what sort of objects your labels are (text or annotation), so I'll just show how to do this programmatically using the text command, which creates labels in axes coordinates (as opposed to figure coordinates). This doesn't solve the problem entirely, but it looks better, possibly to an acceptable degree:
function q56624258
x = linspace(0,2*pi);
y = sin(x);
hF = figure('Position',[-1500 174 760 729]);
%% Create plots
[hAx,hYL] = deal(gobjects(4,1));
for ind1 = 1:3
hAx(ind1) = subplot(2,2,ind1, 'Parent' , hF);
plot(hAx(ind1), x,y.^ind1);
hYL(ind1) = ylabel("plot" + ind1);
end
hAx(4) = subplot(2,2,4);
plot(hAx(4), x,abs(y));
hYL(4) = ylabel('plot4');
%% Add texts (in data coordinates; x-position is copied from the y-label)
for ind1 = 1:4
text(hAx(ind1), hYL(ind1).Position(1), 1.1, ['(' char('a'+ind1-1) ')'], ...
'HorizontalAlignment', 'center');
end
Note several modifications to your code:
The handles returned by some functions that create graphical elements are now stored (mainly: hAx, hYL).
All functions that create graphical elements (subplot, plot, ylabel) now have the target (i.e. parent or container) specified.
I changed the 'Position' of the figure so that it works in my setup (you might want to change it back).
I have a problem with saving a Matlab figure as ".svg" and subsequently opening it in Inkscape. More precisely, I need two subplots to be a specific height, i.e. 6cm. This can be done in Matlab by setting the "Position" property (and setting the units to "centimeters"). This all works as expected and I then export the figure as ".svg"
The problem is that when I import the figure to Inkscape the axes length is close to the value I set but not correct. I.e. I set it to 6 cm and it is 6.28 in Inkscape. It is not much of an error, but it completely defeats the purpose of defining it in the first place. Any ideas?
I tried exporting the figure in several different ways but the result is always the same.
figure('name','representative plasticity figure');
set(gcf,'Color','w','units','centimeters','position',...
[0 0 8.6 8.4],'PaperPositionMode','auto');
s1=subplot(2,1,1)
img = imagesc(magic(8)); hold on;
set(gca, 'TickDir','out','FontSize',8.5,'LineWidth',0.59,'TickLength'...
,[0.03 0.00001]);
c1 = colorbar; c1.Box = 'off';c1.TickDirection = 'out'; c1.FontSize = 8.5;
ax1 = gca; ax1.Units = 'Centimeters';ax1.Position(3:4) = [3.427, 1.59];
box off; % THIS IS THE SIZE I NEED BUT WHICH ISN'T PRINTED CORRECTLY
c1.Label.String = '[whatever]';
subplot(2,1,2)
p1=plot(randi(5,5),'r','LineWidth',0.64); hold on;
box off; set(gca, 'TickDir','out','TickLength',...
[0.03 0.00001],'FontSize',8.5,'LineWidth',0.64);% legend('pre','post');
legend('boxoff');
ax2 = gca;ax2.Units = 'Centimeters';ax2.Position(3:4) = ax1.Position(3:4);
xlabel ('whatever' ); ylabel('whatever');
print myplot -dsvg
The size of the figure should be [3.427, 1.59] in cm. And it is so in the resulting matlab figure, however, in Inkscape it is more like 3.6 and 1.7.
I am currently having trouble while adding transparency to my pie charts.
I can't set using FaceAlpha or EdgeAlpha and using alpha alone kind of rips the edges of the chart when compiling the eps file.
Any tips?
figure;
subplot(1,2,1)
h=pie3(P1,[0 0 0 1 1])
set(h,'EdgeColor','none','LineStyle','none')
hold on
colormap cool
hold on
subplot(1,2,2)
h=pie3([PF PG],[1 0 ],{'X1','X2'})
set(h,'EdgeColor','none')
colormap cool
%alpha(0.5)
print teste -depsc2
The output of pie3 is an array of handles. Some are handles to surfaces, some are to patches, and others are for text. You need to select the sub-set of these handles that actually have EdgeAlpha and FaceAlpha properties. You can do this using findobj.
h = pie3(rand(1,5), [0 0 0 1 1]);
set(findobj(h, '-property', 'FaceAlpha'), 'FaceAlpha', 0.2);
set(findobj(h, '-property', 'EdgeAlpha'), 'EdgeAlpha', 0);
When exporting to an EPS though, transparency is not supported. Also, since you have transparency in your figure, MATLAB will use the OpenGL renderer which causes EPS files to not be rendered as you expect. You could try to use export_fig to get a better result.
It is really difficult to figure out what you are asking.
My code sample shows a way for tighter control over objects inside a figure.
I hope you can modify my example to something you can work with.
(If it isn't, please insert images, and more detailed information about your problem, and also add values of P1, PF, PG).
Matlab orders figure objects is a kind of "tree" structure.
The structure is:
figure -> axes-> object
object
...
object
-> axes-> object
object
...
object
The axes is a children of a figure, and objects are children of axes.
The following code gets array of axes handles:
%Get handles to two axes inside figure;
h_axes_arr = get(gcf, 'Children');
The following code gets array of objects handles (children of first axes):
%Array of handles - children of first axes.
h_arr = get(h_axes_arr(1), 'Children');
h = h_arr(1);
get(h, 'Type') Query the type of the first object.
Here is my code sample:
P1 = [1,3,0.5,2.5,2];
PF = 1;
PG = 2;
figure;
subplot(1,2,1)
h=pie3(P1,[0 0 0 1 1]);
set(h,'EdgeColor','none','LineStyle','none')
hold on
colormap cool
hold on
subplot(1,2,2)
h=pie3([PF PG],[1 0 ],{'X1','X2'});
set(h,'EdgeColor','none')
colormap cool
%alpha(0.5)
%Get handles to two axes inside figure;
h_axes_arr = get(gcf, 'Children');
%Array of handles - children of first axes.
h_arr = get(h_axes_arr(1), 'Children');
for i = 1:length(h_arr)
%Handle to specific children.
h = h_arr(i);
if (isequal(get(h, 'Type'), 'surface'))
%Set trasparency only if handle type is 'surface'
set(h, 'FaceAlpha', 0.5); %Set Alpha to 0.5
end
end
%Array of handles - children of second axes.
h_arr = get(h_axes_arr(2), 'Children');
for i = 1:length(h_arr)
%Handle to specific children.
h = h_arr(i);
if (isequal(get(h, 'Type'), 'surface'))
%Set trasparency only if handle type is 'surface'
set(h, 'FaceAlpha', 0.3); %Set Alpha to 0.5
end
end
%print teste -depsc2
Result:
I know it's ugly...
I hope you can make something useful out of it.
I have some points in a 'jet' colormap. The points have a coefficient that can go from 0 to 1, but usually they dont cover all the range, e.g 0.75-0.9.
When I plot those points I colour them so 0.75 is the lesser colour in the colormap and 0.9 is the maximum color in the colormap, so all the colormap is shown. What I want to do is show that in the colorbar also. When I plot the colorbar the labels on it go to 64, but I want them from 0.75 to 0.9. How can I do that?
EDIT
I don't think the code itself helps a lot but here it goes, just in case. In the colors variable I convert the ZNCC to the range of the colormap.
EDIT2
I found the reason why caxis is not working for me. Here is the code:
%this is why it doesnt work
im=imread('someimageyouwanttotest_inRGB.png')
imshow(im)
points=[1, 2;1 , 2 ;0.3,0.7]
ZNCC=points(3,:)
cmap=colormap('jet');
colors=cmap(round( ((1-min(ZNCC))+ZNCC-1).*(size(cmap,1)-1)/max((1-min(ZNCC))+ZNCC-1))+1,: );
hold on
for i=1:length(ZNCC)
plot(points(1,i),points(2,i),'.','Color',colors(i,:));
end
colorbar()
hold off
I think that is your code displays all your colours correctly then rather just set up the colour bar first on no image:
points=[1, 2;1 , 2 ;0.3,0.7]
ZNCC=points(3,:)
cmap=colormap('jet');
caxis([min(ZNCC) max(ZNCC)]);
colorbar();
hold on
%this is why it doesnt work
im=imread('someimageyouwanttotest_inRGB.png')
imshow(im)
colors=cmap(round( ((1-min(ZNCC))+ZNCC-1).*(size(cmap,1)-1)/max((1-min(ZNCC))+ZNCC-1))+1,: );
for i=1:length(ZNCC)
plot(points(1,i),points(2,i),'.','Color',colors(i,:));
end
hold off
I can't test it as I don't have imshow :/
If caxis is not working for you, you could store the return from colorbar - it is a handle to the colorbar object. Then you can set its properties, like 'YTick' and 'YLim'. The full list of properties you can set is the same as the Axes Properties (because the colorbar is just an axes object, after all).
Here is an example:
% Generate some random data
z = rand(10);
[x, y] = meshgrid(1:size(z, 1));
% Plot colour map
pcolor(x, y, z);
shading interp; % Comment out to disable colour interpolation
colormap jet;
% Setup colorbar
c = colorbar();
set(c, 'YTick', [0.75 0.875 1]); % In this example, just use three ticks for illustation
ylim(c, [0.75 1]);
It is only necessary to do this once, after you've finished plotting.
Edit: If you need the limits and ticks automatically from the data, then you can do something like
% Find the limits
lims = [min(z(:)) max(z(:))];
% Function for rounding to specified decimal places
dprnd = #(x, dps)round(x*(10.^dps))./(10.^dps);
% Generate ticks
nTicks = 5;
nDps = 2;
ticks = dprnd(linspace(lims(1), lims(2), nTicks), nDps);
set(c, 'YTick', ticks);
In MATLAB, I plot many different vectors to a figure. Now, what I would like to do is simply undo the last vector that I plotted to that figure, without clearing everything else. How can this be accomplished? Can it be accomplished?
Thanks
Edit:
figure(1); clf(1);
N = 100;
x = randn(1,N);
y = randn(1,N);
z = sin(1:N);
plot(x); hold on;
plot(y,'r');
plot(z,'k');
Now here, I would like to remove the plot z, which was the last plot I made.
If you know before plotting that you want to remove it again later, you can save the handle returned by plot and delete it afterwards.
figure;
h1 = plot([0 1 2], [3 4 5]);
delete(h1);
Try
items = get(gca, 'Children');
delete(items(end));
(or maybe delete(items(1)))
The answer that #groovingandi gives is the best way to generally do it. You can also use FINDALL to find the handle based on the properties of the object:
h = findall(gca, 'type', 'line', 'color', 'k');
delete(h);
This searches the current axes for all line objects (plot produces line objects) that are colored black.
To do this on, say, figure 9, you need to find the axes for figure 9. Figure handles are simply the figure number, so:
ax = findall(9, 'axes');
h = findall(ax, 'type', 'line', 'color', 'k');
delete(h);