matlabs plotyy with axis for each plot only on one side - matlab

The following code shows my problem. plotyy completely fails if the ticks are not at the same positions on both sides (which is rather the normal case...)
I require a plot with two y axis but the ticks only on one side. I was suggested to use addaxis, but I do not see how that helps me, since I do not want separated axis.
clf;
clc;
xaxis = 0:0.1:25;
ydata1 = linspace(12.1712,12.7679, length(xaxis));
ydata2 = linspace(0.3597,-28.7745, length(xaxis));
[AX,H1,H2] = plotyy(xaxis, ydata1, xaxis, ydata2);
% axis limits - x axis (min to max)
xlimits(1) = min(xaxis); xlimits(2) = max(xaxis);
set(AX, 'XLim', xlimits);
set(AX(2),'XTick',[]);
% y1 axis limits
ylimits(1) = min(ydata1); ylimits(2) = max(ydata1);
ylimits(2) = ylimits(2) + (ylimits(2)-ylimits(1))*0.05;
set(AX(1), 'YLim', ylimits);
% y2 axis limits
ylimits(1) = min(ydata2); ylimits(2) = max(ydata2);
ylimits(2) = ylimits(2) + (ylimits(2)-ylimits(1))*0.05;
set(AX(2), 'YLim', ylimits);
% y1 ticks
set(AX(1),'YTick',[12.0:0.1:12.8]);
% y2 ticks
set(AX(2),'YTick',[-25:5:0]);
print(gcf, ['-r' num2str(400)], ['test' '.png' ], ['-d' 'png']);

to Matthias,
set the XAxisLocation to top, and disable the XTickLabel. the upper line is back now :)
set(AX(2),'XAxisLocation','top', 'XTickLabel',[])

Try setting the ticks to empty set:
set(AX(2),'YTick',[]);
or
set(AX(1),'YTick',[]);
Edit(1): You can manually create the labels for left side and set the right side to []:
clf;
clc;
xaxis = 0:0.1:25;
ydata1 = linspace(12.1712,12.7679, length(xaxis));
ydata2 = linspace(0.3597,-28.7745, length(xaxis));
[AX,H1,H2] = plotyy(xaxis, ydata1, xaxis, ydata2);
% axis limits - x axis (min to max)
xlimits(1) = min(xaxis); xlimits(2) = max(xaxis);
set(AX, 'XLim', xlimits);
set(AX(2),'XTick',[]);
% y1 axis limits
ylimits(1) = min(ydata1); ylimits(2) = max(ydata1);
ylimits(2) = ylimits(2) + (ylimits(2)-ylimits(1))*0.05;
set(AX(1), 'YLim', ylimits);
x = linspace(ylimits(1),ylimits(2),10);
ticks1 = arrayfun(#(t){sprintf('%2.2f',t)},x);
% y2 axis limits
ylimits(1) = min(ydata2); ylimits(2) = max(ydata2);
ylimits(2) = ylimits(2) + (ylimits(2)-ylimits(1))*0.05;
x = linspace(ylimits(1),ylimits(2),10);
ticks2 = arrayfun(#(t){sprintf('%2.2f',t)},x);
set(AX(2), 'YLim', ylimits);
ticks = cell(size(ticks1));
for i=1:numel(ticks1)
ticks{i} = sprintf('%s / %s',ticks1{i},ticks2{i});
end
% y1 ticks
set(AX(1),'YTickLabel',ticks);
% % y2 ticks
set(AX(2),'YTick',[]);

Here is an approach that I got from the mathworks forum. The idea is to remove the box property, which creates the tics on the opposite side.
set(AX(1),'Box','off') % Turn off box of axis 1, which removes its right-hand ticks
set(AX(2),'Box','off') % Turn off box of axis 2, which removes its left-hand ticks
The downside is, that the upper line disappears. If someone knows how to get it back that would be great. Mybe with an empty plot over the current plot with the same dimensions??

Here is a solution using a third axis. For this solution first turn boxes of as suggested
set(ax(1),'Box','off') % Turn off box of axis 1, which removes its right-hand ticks
set(ax(2),'Box','off') % Turn off box of axis 2, which removes its left-hand ticks
Now, additionally add a third axis at the same position.
ax3 = axes( 'Position', get(ax(1), 'Position'),...
'XAxisLocation', 'top',...
'XTickLabel', my_XTickLabels_on_top,...
'YColor', 'none',...
'YTick', [],...
'YTickLabel', [],...
'Color', 'none', ...
cell_with_further_pValPairs{:});
One can also link the 'x' axis of all axes objects. The limits and ticks will then get updated accordingly.
linkaxes([ax ax3], 'x')
This will, however, not properly update the ticks of the third axis, unless you write a proper callback, which got even more tricky to do in MATLAB 2014b and above
To make the 'real' axes the current axes, it is possible to use
axes(ax)
Example:

Related

create bins based on a range of values for histogram figure

I am doing some analysis and need to produce a histogram plot. I know how to create the standard histogram plot but I need something like the image below, where each point is an interval on the x axis. Each bin is based on a value from x-x for example.
You can use the histogram function, and then set the XTick positions and XTickLabels accordingly. See the comments in the code for explanation.
% random normally distrubuted data
x = 1*randn(1000,1);
edges = -5:1:5;
% create vector with labels (for XTickLabel ... to ...)
labels = [edges(1:end-1); edges(2:end)];
labels = labels(:);
% plot the histogram
figure();
ax = axes;
h = histogram(x, 'BinEdges', edges, 'Normalization', 'Probability');
ax.XTick = edges + mean(diff(edges)/2);
ax.XTickLabel = sprintf('%.1f to %.1f\n', labels);
ax.XTickLabelRotation = 90;
% set yticks to percentage
ax.YTickLabel = cellfun(#(a) sprintf('%i%%', (str2double(a)*100)), ax.YTickLabel, 'UniformOutput', false);
% text above bars
bin_props = h.BinCounts/numel(x); % determine probabilities per bin in axis units
bin_centers = ax.XTick(1:end-1); % get the bin centers
txt_heigts = bin_props + 0.01; % put the text slightly above the bar
txt_labels = split(sprintf('%.1f%% ', bin_props*100), ' ');
txt_labels(end) = []; % remove last cell, is empty because of split.
text(ax, bin_centers, txt_heigts, txt_labels, 'HorizontalAlignment', 'center')
% set ylim to fit all text (otherwise text is outside axes)
ylim([0 .4]);
Putting the text at the right location may require some tweaking. Most important is the 'HorizontalAlignment' option, and the distance to the bars. I also used the 'Normalization', 'probability' option from the histogram function, and set the y axis to also show percentages.
I figure you can make the addition below yourself when needed.
When your data can be outside of the defined binedges, you can clip your data, and set the XTickLabels with less than or greater than signs.
% when data can be outside of defined edges
x = 5*randn(1000,1);
xclip = x;
xclip(x >= max(edges)) = max(edges);
xclip(x <= min(edges)) = min(edges);
% plot the histogram
figure();
ax = axes;
h = histogram(xclip, 'BinEdges', edges);
ax.XTick = edges + mean(diff(edges)/2);
ax.XTickLabel = sprintf('%.1f to %.1f\n', labels);
ax.XTickLabelRotation = 90;
% set boundary labels
ax.XTickLabel{1} = sprintf('\\leq %.1f', edges(2));
ax.XTickLabel{end-1} = sprintf('\\geq %.1f', edges(end-1));
You can also set the outer edges to -Inf and Inf, as user2305193 pointed out. Since the outer bins are then much wider (because they actually extend to Inf on the x axis), which you can correct by setting the axis xlim. By the default the XTickLabels will display -Inf to -5.0, which I personally don't like, so I set them to lesser (and equal) than and greater than signs.
step = 1;
edges = -5:step:5; % your defined range
edges_inf = [-Inf edges Inf]; % for histogram
edges_ext = [edges(1)-step edges]; % for the xticks
x = 5*randn(1000,1);
% plot the histogram
figure();
ax = axes;
h = histogram(x, 'BinEdges', edges_inf, 'Normalization', 'probability');
labels = [edges_inf(1:end-1); edges_inf(2:end)];
labels = labels(:);
ax.XTick = edges_ext + step/2;
ax.XTickLabel = sprintf('%.1f to %.1f\n', labels);
ax.XTickLabelRotation = 90;
% show all bins with equal width (Inf bins are in fact wider)
xlim([min(edges)-step max(edges)+step])
% set boundary labels
ax.XTickLabel{1} = sprintf('\\leq %.1f', edges(1));
ax.XTickLabel{end-1} = sprintf('\\geq %.1f', edges(end));

Matlab - remove xtick with a bar plot

I get the following figure with a bar plot :
I would like to remove the XTick with red circles but keep Xtick for the middle of each group of bars (i.e 1024, 10240, 102400, 1024000, 10240000).
I generate this image with the Matlab script below :
x = load('performances.txt');
% Get Runtimes
for i = 1:6
time_seq(1:5,i) = x((i-1)*5+1:i*5,3);
time_gpu(1:5,i) = x((i-1)*5+1:i*5,4);
speedup(1:5,i) = time_seq(1:5,i)./time_gpu(1:5,i);
end
% X axis
sizeArray = [1024 10240 102400 1024000 10240000 102400000]
figure(1);
% Get Histogram
h = bar(log10(sizeArray),log10(speedup(1:5,:)')); % get histogram
% Log10 for x-axis and xtick
set(gca,'Xtick',log10(1024):1:log10(1.024*10^8))
set(gca,'Xticklabel',10.^get(gca,'Xtick'));
set(h(1),'facecolor',[0.5 0.5 1]);
set(h(2),'facecolor',[1 0.5 0.5]);
set(h(3),'facecolor',[0.5 1 0.5]);
set(h(4),'facecolor',[0.5 0.5 0.5]);
set(h(5),'facecolor',[1 0.5 1]);
hPatch = findobj(h,'Type','patch');
set(hPatch,'facealpha',1);
grid on;
title('Benchmark GPU vs CPU');
% Size of WorkGroup
h = legend('N=16','N=32','N=64','N=128','N=256');
v = get(h,'title');
set(v,'string','WorkGroup size');
% Place legend
rect = [0.6,0.25,0.2,0.2];
set(h,'Position',rect,'color','w');
hPatch = findobj(h,'Type','patch');
set(hPatch,'facealpha',1);
xlabel('log(Array size)');
ylabel('log(Speedup)');
% Make right y-axis visible
ax1 = gca;
ax2 = axes('Position', get(ax1, 'Position'));
set(ax2, 'YAxisLocation', 'right', 'Color', 'none', 'XTickLabel', []);
set(ax2, 'YLim', get(ax1, 'YLim'));
I tried different things but couldn't make them disappear, anyone would have an idea or a clue ?
Thanks
It happens because of the last 3 lines in your code where you add the Y-axis from the right side. You need to add the following line at the end:
set(ax2,'XTick',[]);
Here is my result (with fake data):

Zoom region within a plot in Matlab

I'm using Matlab to produce figures, and I'm wondering if there is a way to plot a zoomed region in a figure of the overall data?
I have scatter data plotted over one week, with the x-axis in hours, and I want to zoom into the first 3 hours, and display them within the main figure with the x-axis label of minutes.
The plotting code I have so far is as follows:
allvalsx = marabint(:,2)
allvalsy = marabint(:,5)
subvalsx = marabint(1:7,2);
subvalsy = marabint(1:7,2);
%% Plots the scatter chart.
sizemarker = 135
handle = scatter(allvalsx, allvalsy, sizemarker, '.')
figure(1)
axes('Position',[.2 .2 .2 .2])
handle2 = scatter(subvalsx, subvalsy, '.r')
title(plotTitle)
xlabel('Time since treatment (hours)')
ylabel('Contact angle (deg)')
% Axis scales x1, x2, y1, y2
axis([0, marabint(length(marabint),2) + 10, 0, 120]);
% This adds a red horizontal line indicating the untreated angle of the
% sample.
untreatedLine = line('XData', [0 marabint(length(marabint),2) + 10], 'YData', [untreatedAngle untreatedAngle], 'LineStyle', '-', ...
'LineWidth', 1, 'Color','r');
% Adding a legend to the graph
legendInfo = horzcat('Untreated angle of ', untreatedString)
hleg1 = legend(untreatedLine, legendInfo);
% This encases the plot in a box
a = gca;
% set box property to off and remove background color
set(a,'box','off','color','none')
% create new, empty axes with box but without ticks
b = axes('Position',get(a,'Position'),'box','on','xtick',[],'ytick',[]);
% set original axes as active
axes(a)
% link axes in case of zooming
linkaxes([a b])
set(gcf,'PaperUnits','inches');
set(gcf,'PaperSize', [8.267 5.25]);
set(gcf,'PaperPosition',[0 0.2625 8.267 4.75]);
set(gcf,'PaperPositionMode','Manual');
set(handle,'Marker','.');
print(gcf, '-dpdf', '-r150', horzcat('markertest4.pdf'));
This produces the following
Can anyone help me out with this?
yeah, I think I know what you need. Try this:
zoomStart = 0;
zoomStop = 3;
set(gca, 'XLim', [zoomStart zoomStop])
Let me know if that doesn't do what you need, and I'll give you a different way.

Multiple axis plot

I have to plot some data and I need two x and y axes.
The main x and y give me displacement infos, the secondary (x on top and y on the right) give me infos on energy.
The issue I have is that if I make the plot window bigger the secondary axes don't resize properly and, but it is very minor, the plot title is written under the tool bar and I can see only the lower part of the letters.
Someone knows how to fix the main issue on secondary axes?
The code I used for secondary axis is:
figure(1)
%%%%voglio fare un plot tenendo fisse le dimensioni delle icone nella legenda
hplot = plot(yH(1,:),xH(1,:),'^', yC(:,1),xC(:,1),'*',yC(:,2),xC(:,2),'*',...
yC(:,3),xC(:,3),'*',yC(:,4),xC(:,4),'*',yC(:,5),xC(:,5),'*',...
yC(:,6),xC(:,6),'*','MarkerSize',s); % Markersize: specifys the size of the marker in points (s in questo caso)
hold on
plot(Ymcporigine,Xmcporigine,'k-','MarkerEdgeColor','k','MarkerSize',1); %Plot contorno MCP
hold on
plot(Yh, Xh, 'b-', 'MarkerSize', s); %Plot alone circolare
hold off
%Labe assi principali - It is necessary to give the label instructions after plot in order to avoid overlap
xlabel(gca, 'Deflessione magnetica [m]'); % label lower x axis
ylabel(gca,'Deflessione elettrica [m]'); %label left y axis
%particles outside MCP radius won't be appear in figure
xlim([0, Rmcp])
ylim([0, Rmcp])
%%%% legenda assi principali
l=legend(hplot, 'H^+','C^+','C^{+2}','C^{+3}','C^{+4}','C^{+5}','C^{+6}', 'Location','BestOutside');
a=get(l,'children');
set(a(1:3:end),'MarkerSize',10);
%%%% doppio Asse x
%xlabel(gca, 'Deflessione magnetica [m]'); % label asse x principale
%set secondary x limit as the momentum of a H+ at distance equal to the MCP radius
% Secondo Harres y=(q*B*LB*L)/sqrt(2mEkin) ==> mv=q*B*LB*L/y
mv_max = (q*B*LB*L)/Rmcp;
%mv_max = 1;
%Layout instruction
set(gca,'Box','off'); % Turn off the box surrounding the whole axes
axesUnits=get(gca,'Units');
axesPosition = get(gca,'Position'); %# Get the current axes position
hNewAxes = axes('Position',axesPosition,... %# Place a new axes on top...
'Units', axesUnits,...
'ActivePositionProperty', 'OuterPosition',...
'Color','none',... %# ... with no background color
'XAxisLocation','top',... %# ... located on the top
'Ytick', [],... %# ... with no y tick marks
'Xlim', [0, mv_max],... %# ... should define x axis scale (need to set xmax = mv_max)
'Box','off'); %# ... and no surrounding box
xlabel(hNewAxes,'Momentum (H^+)'); %# Add a label to the top axis
set(gca, 'XTickLabel', num2str(get(gca,'XTick')','%g'))
%%%%%Plot title - It is necessary to give the title instruction after secondary x axis in order to avoid overlap
title(['Calcolo approssimato interazione ioni campo magnetico B=', num2str(B), 'Tesla']);
%%%% doppio Asse y
%ylabel(gca,'Deflessione elettrica [m]'); %label asse y principale
%set secondary y limit as the energy of a H+ at distance equal to the MCP radius
% Secondo Harres x=(q*E*Le*L)/(2mEkin) ==> Ekin=q*E*Le*L/2mx
Le = 0.07; %Estensione del C.E. : 70 mm
E = 100000; %campo TP.m
Ekin_max = (q*E*Le*L)/(2*m_H*Rmcp);
%mv_max = 1;
set(gca,'Box','off'); % Turn off the box surrounding the whole axes
axesUnits = get(gca,'Units');
axesPosition = get(gca,'Position'); %# Get the current axes position
hNewAxes = axes('Position',axesPosition,... %# Place a new axes on top...
'Units', 'normalized',...
'ActivePositionProperty', 'OuterPosition',...
'Color','none',... %# ... with no background color
'YAxisLocation','right',... %# ... located on the right
'Ylim', [0, Ekin_max],... %# ... should define y axis scale (need to set ymax=Ekin_max)
'Xtick', [],... %# ... with no y tick marks
'Box','off'); %# ... and no surrounding box
ylabel(hNewAxes,'Energy (H^+)'); %# Add a label to the top axis
set(gca, 'YTickLabel', num2str(get(gca,'YTick')','%g'))
I remembered seeing this walkthrough on how to set up multiple axes in the Matlab documentation. I tried their sample code and everything resizes fine.
Where your code differs from the Matlab documentation, is that you need to define your x axis and y axis at the same time, not in two different new-axis statements. So take out your two hNewAxes statements and replace it with one that includes all the properties:
hNewAxes = axes('Position',axesPosition,... %# Place a new axes on top...
'Units', 'normalized',...
'ActivePositionProperty', 'OuterPosition',...
'Color','none',... %# ... with no background color
'YAxisLocation','right',... %# ... located on the right
'XAxisLocation','top',...
'Xlim', [0, mv_max],...
'Ylim', [0, Ekin_max],... %# ... should define y axis scale (need to set ymax=Ekin_max)
'Box','off'); %# ... and no surrounding box
If you want to plot some of your data lines with respect to one set of axes, and some with respect to the second, then for the second set you'll have to plot them in the style laid out at the end of the walkthrough:
hl2 = line(x2,y2,'Color','k','Parent',ax2);
where the 'Parent' property tells Matlab which axes to use.
From the Matlab docs it looks like you should set the ActivePositionProperty as OuterPosition instead of Position. I can't reproduce the scaling issue, but setting that does seem to adjust the title position.

Plot outside axis in Matlab

How to plot something outside the axis with MATLAB? I had like to plot something similar to this figure;
Thank you.
Here is one possible trick by using two axes:
%# plot data as usual
x = randn(1000,1);
[count bin] = hist(x,50);
figure, bar(bin,count,'hist')
hAx1 = gca;
%# create a second axis as copy of first (without its content),
%# reduce its size, and set limits accordingly
hAx2 = copyobj(hAx1,gcf);
set(hAx2, 'Position',get(hAx1,'Position').*[1 1 1 0.9], ...
'XLimMode','manual', 'YLimMode','manual', ...
'YLim',get(hAx1,'YLim').*[1 0.9])
delete(get(hAx2,'Children'))
%# hide first axis, and adjust Z-order
axis(hAx1,'off')
uistack(hAx1,'top')
%# add title and labels
title(hAx2,'Title')
xlabel(hAx2, 'Frequency'), ylabel(hAx2, 'Mag')
and here is the plot before and after:
You can display one axis with the scale you want, then plot your data on another axis which is invisible and large enough to hold the data you need:
f = figure;
% some fake data
x = 0:20;
y = 23-x;
a_max = 20;
b_max = 23;
a_height = .7;
%% axes you'll see
a = axes('Position', [.1 .1 .8 a_height]);
xlim([0 20]);
ylim([0 20]);
%% axes you'll use
scale = b_max/a_max;
a2 = axes('Position', [.1 .1 .8 scale*a_height]);
p = plot(x, y);
xlim([0 20]);
ylim([0 b_max]);
set(a2, 'Color', 'none', 'Visible', 'off');
I had similar problem and I've solved it thanks to this answer. In case of bar series the code is as follows:
[a,b] = hist(randn(1000,1)); % generate random data and histogram
h = bar(b,a); % plot bar series
ylim([0 70]) % set limits
set(get(h,'children'),'clipping','off')% turn off clippings