How to get length of YTickLabels in MATLAB? - matlab

I have a MATLAB subplot figure. I need the YLabels to left align justify. To do this I am setting the Position property for each ylabel. My problem is the subplots are being created programmatically and therefore I don't know what to set the position as.
In MATLAB I want to use the longest/widest YTickLabel as a reference point for positioning. To do that I want to get the length of each label. I am able to get the YTickLabels by doing:
% Set Label format as string
set(gca, 'YTickLabel', num2str(transpose(get(gca, 'YTick'))))
% Get axis YTickLabels
ax = gca;
labels = get(ax, 'YTickLabel');
% Print labels to console
disp(labels)
I would like to iterate through the labels and find the length of the longest label. I've tried accessing them as a cell array but get 'Cell contents reference from a non-cell array object error.' And when I try matrix indexing nothing prints.
Does anyone know if it is possible to get the length of each individual YTickLabel value?
Useful info:
MATLAB R2014b

By "length of each individual YTickLabel value" I understand that you wish to get the number of characters forming each label.
It's quite easy using the numel function, which outputs the number of elements in a cell for an example. Since labels are stored in a cell array, we can use the fancy function cellfun to apply numel to each cell, then convert to a numeric array with cell2mat
In short you can use this:
LabelLength = cell2mat(cellfun(#(x) numel(x),labels,'uni',0))
here is some sample code to illustrate:
clear
clc
close all
x = 1:5;
y = rand(size(x));
scatter(x,y,40,'r','filled')
set(gca,'YTick',[1 3 5],'YTickLabel',{'One';'ThisIsThree';'AndFive'})
grid on
labels = get(gca,'YTickLabel')
LabelLength = cell2mat(cellfun(#(x) numel(x),labels,'uni',0))
and output:
LabelLength =
3
11
7
You could replace cellfun with this equivalent for-loop:
LabelLength = zeros(numel(labels),1);
for k = 1:numel(labels)
LabelLength(k) = numel(labels{k});
end
LabelLength
Note that as a workaround offering quite a lot of flexibility, you could replace the YTickLabels by text objects, for which you can set the HorizontalAlignment property to left for the text to be left-justified.
Hope that helps!

Related

how to decrease the legend width in matlab

I am using the matlab to plot some project figures, see the blow figure. Now I am trying to cut the legend width so that the line won't look so wide. I tried these command as suggest by Benoit_11:
[~,icons,~,~] = legend(leg,'location','northwest');
hline = icons(2);
linedata = get(hline,'xdata');
newdata = [linedata(1)+0.2 linedata(2)];
set(hline,'xdata',newdata,'linewidth',1)
I am using the for loop to plot these figures because I have multiple figures to analysis at the same time. Now I can change the length of the legend line right now. But I got another problem: if I have different length of legend text, even if I set the same starting point and end point, I will get different length for the line in the end (you can see that from the figures). I tried to modify icon(1) but always got the error. Any suggestions?
There are 2 things you are not doing right with your code (aside the fact that you use size as the handles to the legend...that's risky because size is a built-in function):
1) Calling legend with only 1 argument returns a handle to the legend object and getting its position actually gives you the position of the box enclosing the legend, i.e. the text + the line.
2) Using this line:
p(3) = p(3) - 0.06;
does modify the position, however you would need to set the new position of the legend with something like the following for the changes to be effective:
set(HandleToLegend,'Position',p)
To come back to your question, the trick is to assign many outputs during the call to legend; you can then modify specific elements of the legend object.
Actually we only need 1 of the 4 output arguments, called icons in the docs so I'll stick with the notation. Then, we can get the XData property of the line and modify it as we want. The XData is actually a 2-element vector:
[StartingPoint EndingPoint]
so changing one or the other (or both) will change the length of the line displayed in the legend box.
Here is the whole code with comments; I changed the length and linewidth of the line in the 2nd plot to highlight the changes.
clear
clc
close all
x = 1:10;
y = rand(1,10);
figure;
%// Default case
subplot(1,2,1)
plot(x,y);
legend('First plot','Location','NorthWest');
title('Before','FontSize',18);
%// With modifications
subplot(1,2,2)
plot(x,y);
title('After','FontSize',18);
%//========================
%// Change the legend here
%//========================
%// The "icons" output is what you want
[~,icons,~,~] = legend('First plot','Location','NorthWest');
%// icons(1) is the text of the current element in the legend Here its 'First plot'
i_1 = get(icons(1)); %// access the properties with this command.
%// icons(2) is the line associated with that text. Here the blue line.
i_2 = get(icons(2));
%// Mhh I don't know what icons(3) represents haha sorry about that.
i_3 = get(icons(3));
%// Get the actual line
hline = icons(2);
%// Fetch its XData property
LineData = get(hline,'XData')
%// Play with those 2 elements to see the output change.
NewData = [LineData(1)+.2 LineData(2)-.01];
%// Apply the changes
set(hline,'XData',NewData,'LineWidth',3)
Which gives the following:
You need to set the value of the Position property, you can just change the vector p. p does not affect the plot at all, it's just a vector of numbers. You have to modify it, then apply it back to the plot, using
set(size,'Position',p)
There does seem to be a minimum width of the legend however.

how to change size(out) = [m n] in matlab

This is a continuation of my previous problem, so now i want to know how to change array size and how to use size(out) = [m n].
so basically if you have 10x10 array and you want to plot column 9 vs. column 10 in scatter plot, and you want column 1-column 8 to be the labels of your scatter plot. how can i use size(out) = [10 10]?
for someone who want examples:
Auto-Label in scatter plot using matlab
and what if your array is m x n? is there a general code for this? please enlighten me, thanks.
To make things more general you can make use of the end keyword, which refers to the last row/column or an array/cell array/anything in Matlab (actually "last array of index").
Revisiting your example, you could use num2str (alternatively to sprintf) and use the following:
scatter(out(:,end-1), out(:,end));
for k = 1:size(out,1)
T{k} = num2str(out(k,1:end-2));
end
xshift = 0.03; yshift = 0.03;
text(out(:,3)+xshift, out(:,4)+yshift, T);
grid on
Which gives this:

Multiple colormaps using bar(z,'stacked')

I have read the article recommended by a post on another colormap thread http://www.mathworks.com/matlabcentral/answers/101346 and I understand the concept. I am having trouble understanding the values of CDATA when using the bar(z,'stacked') function.
I have one figure with a major axis plotted using cmap, and I have created and positioned a new axis for the bar chart and I want it to use cmap2.
For example, my code includes:
maps = colormap([cmap;cmap2]);
bH = bar(z,'stacked');
Where z = 25x10 (annual data for 10 years over 25 sites)
Now when I look at the CDATA
get(bH,'CDATA') A cell array is returned of size 1x10 with each cell containing the string 'scaled'.
Now if I look at the CDATA of each of the children
childH = get(bH,'children');
get(childH{i},'CDATA')
A matrix of size 25x10 is returned with every value equal.
e.g. childH{i}'s CDATA is a matrix of size 25x10 having all values = i
So how can I scale these to map to my colormap since
from the documentation above I need to perform:
m = size(colormap,1); % Number of colors in the current colormap
Data = get(H,'CData') % Where H is a handle to a surface or patch object
cmin = min(CData(:)); % Minimum color value
cmax = max(CData(:)); % Maximum color value
idx = min(m,round((m-1)*(CData-cmin)/(cmax-cmin))+1);
idx becomes min(m,nan) which is always m?
I really need help understanding this.
Am I missing something or is this function a special case?
First make sure that cmap2 has exactly the number of colors that you want to use, then get the barseries object to map into it directly. Something like:
childH = get(bH, 'children');
for a = 1:numel(childH)
C = get(childH{a}, 'FaceVertexCData');
C(:) = a+size(cmap, 1);
set(childH{a}, 'FaceVertexCData', C, 'CDataMapping', 'direct');
end

Changing how many tick labels on a plot in MATLAB

I have 3 arrays,
y = [1,4,6,8,2,5,......];
x = [1,2,3,4,5,6,......];
xlabel = {'label1','label2','label3',........};
where each element in xlabel is the label for each element of the x array.
I am plotting this using:
plot(x,y);
set(gca,'xtick',x,'xticklabel',xlabel);
But because my arrays hold thousands of elements I am getting a black bar as a label because MATLAB is printing every label (see image).
How do I change this so MATLAB only prints a select few of my xlabels?
You can do for example:
selected = 1:100:numel(x); % change the "100" as desired
set(gca,'xtick',x(selected),'xticklabel',xlabel(selected));

How To Put String Labels on Contours for Contour Plots in MATLAB

I am wondering if it is possible to label the contours of a MATLAB contour plot with a set of user-defined strings?
I am currently using the following code snipper to produce a labelled contour plot:
%Create Data
X = 0.01:0.01:0.10
Y = 0.01:0.01:0.10
Z = repmat(X.^2,length(X),1) + repmat(Y.^2,length(Y),1)';
%Create Plot
hold on
[C,h] = contourf(X,Y,Z);
%Add + Format Labels to Plot
hcl = clabel(C,h,'FontSize',10,'Color','k','Rotation',0);
set(hcl,'BackgroundColor',[1 1 1],'EdgeColor',[0 0 0],'LineStyle','-',)
hold off
The issue with this code is that the labels are automatically generated by MATLAB. Even as I can easily change the contours that are labels, I cannot change the labels that they get.
Ideally, I would like to label them with a set of strings that I define myself. However if that is not possible, then I am wondering if it is possible to change the numeric format of the labels. The reason for this is that the code above actually produce a contour plot for an error rate, which I would like to display as a % value (i.e. use 1% in the contour label, instead of 0.01 etc.).
In this case, hcl is actually an array which stores handles to every contour label on your plot. When you set properties using the array (as in your code),
set(hcl, 'name', 'value')
You will set the property of every label to the same value.
You can change the properties of individual labels by iterating over the array. For example, this is how you would add a percentage sign:
for i = 1:length(hcl)
oldLabelText = get(hcl(i), 'String');
percentage = str2double(oldLabelText)*100;
newLabelText = [num2str(percentage) ' %'];
set(hcl(i), 'String', newLabelText);
end