I have a bar graph with 2 different data (each with a different color as you can see on the picture). I would like to move the x-axis so it crosses at y=-100 (for example). So if a data = -40, I would like to have a bar from -100 to -40.
An other question : is it possible to write each value of the x-axis vertically (because with all the values, we can't see anything).
The last question : is it possible to have 2 different scales for the x_axis ?
Thank you in advance,
Best regards,
Here is some code to get you going. Everything is commented so that should be easy to follow:
clear
clc
close all
%// Generate dummy data
y = -90*rand(1,20);
NumY = numel(y);
HalfData = round(NumY/2);
%// Loop to color half in pink and half in blue
hold all
for k = 1:NumY
hBar = bar(k,y(k));
if k <= HalfData
set(hBar,'FaceColor',[1 0 1])
else
set(hBar,'FaceColor',[0 0 1])
end
end
hold off
%// Get xtick labels and position for future use
xtLabels = cellstr(get(gca,'XTickLabel')).';
xtPos = get(gca,'XTick');
%// Change baseline value
set(hBar,'BaseValue',-40)
%// Get baseline to change its properties if you want
hBaseL = get(hBar,'Baseline');
set(hBaseL,'LineStyle','--','Color','k','LineWidth',3)
%// Adjust axis limits. Remove labels to place them vertically
set(gca,'XLim',[0 NumY],'XTickLabel',{''})
%// Get correct position for xlabel text
YLimPoArrays = min(get(gca,'YLim'));
YLimPoArrays = repmat(YLimPoArrays,numel(xtPos),1);
%// Place text positioned vertically with a small y offset
text(xtPos,YLimPoArrays-3,xtLabels,'HorizontalAlignment','center','Rotation',90,'FontSize',15)
And the output:
Hope that helps!
Related
Using Matlab, I want to write a number in a specific position inside an image shown by imshow. At the moment, I have:
myimage = imread('Route of my image');
myimage = im2double(myimage);
imshow(myimage)
MyBox = uicontrol('style','text');
set(MyBox,'String',mynumber);
set(MyBox,'Position',[25,25,15,15]);
My problem is that positions given in 'set' are relatives to all window that manage the figure window so it also includes the gray borders. How can I write them relative to only the figure (without the gray borders)?
You could use text instead?
imshow(image);
text(x,y,'your text')
You can follow the steps described here to remove the grey border from the figure so as to obtain right coordinates when placing the text. Basically fetch the dimensions of both the figure and axes containing the image and make the figure fit exactly the axes.
Beware that when specifying the position of a uicontrol object the 0 position is at the BOTTOM left, whereas the pixel coordinates inside an image start from the TOP left. Therefore you will need to get the dimensions of the image and subtract the actual y-coordinate from the number of rows forming the image, i.e. the 1st dimension.
Here is an example:
clear
clc
close all
myimage = imread('coins.png');
myimage = im2double(myimage);
imshow(myimage);
[r,c,~] = size(myimage);
%// Copied/pasted from http://www.mathworks.com/matlabcentral/answers/100366-how-can-i-remove-the-grey-borders-from-the-imshow-plot-in-matlab-7-4-r2007a
set(gca,'units','pixels'); %// set the axes units to pixels
x = get(gca,'position'); %// get the position of the axes
set(gcf,'units','pixels'); %// set the figure units to pixels
y = get(gcf,'position'); %// get the figure position
set(gcf,'position',[y(1) y(2) x(3) x(4)]);% set the position of the figure to the length and width of the axes
set(gca,'units','normalized','position',[0 0 1 1]) % set the axes units to pixels
%// Example
hold on
mynumber = 20;
%// Set up position/size of the box
Box_x = 25;
Box_y = 25;
Box_size = [15 15];
%// Beware! For y-position you want to start at the top left, i.e. r -
%// Box_y
BoxPos = [Box_x r-Box_y Box_size(1) Box_size(2)];
MyBox = uicontrol('style','text','Position',BoxPos);
set(MyBox,'String',mynumber);
and output:
yay!
The answers above add text on the figure window. If you want to modify your image itself and change the pixels so that you get the text where ever you display the image you can use insertText function available in Computer Vision toolbox.
myimage = imread('Route of my image');
myimage = im2double(myimage);
myimage = insertText(myimage, [25 25], 'your text');
imshow(myimage)
I am trying to create area plots with 2 y-axis using plotyy by using 'area' function. I don't want to have any tick marks or labels or titles but I just want the outside box. I would also like to save just the plot (not the entire figure window) as a png file.
When I turn off the x and y-axis ticks and labels, the box looks thin on the bottom and left, thick on the top and right. What am I doing wrong?
Also, if I try to make the box 'LineWidth' fat, I see two tick marks at the bottom left and bottom right - which ruin the plot and I am unable to remove. Can someone help?
My test code is below:
x = 1:100;
y1 = rand(size(x));
y2 = 100*rand(size(x));
fig_handle = figure('units','inches','position',[1 1 9 3]);
[a,p1,p2] = plotyy(x,y1,x,y2,'area');
c1 = get(p1,'child');
c2 = get(p2,'child');
set(c1,'facea',0.5,'FaceColor','b','EdgeColor',[0 0 0]);
set(c2,'facea',0.5,'FaceColor','r','EdgeColor',[0 0 0]);
set(c1,'Line','None');
set(c2,'Line','None');
set(a,'Layer','top')
set(a,'XTick',[]);
set(a(1),'YTick',[]);
set(a(2),'YTick',[]);
set(a,'TickDir','in')
set(a,'LineWidth',5);
Also, notice how the left Y-axis has red area on it, while the right Y-axis doesn't. Is this fix-able?
Any help would be appreciated! Also, I am new to StackOverflow - so, if these are too many questions in one post, please pardon me and I will post them as separate requests/questions.
Here is a workaround for the red appearing on the left Y-axis.
Since the axes line is quite thick, the data displayed close to it is drawn over it. To avoid this, you can slightly shift the x limits of the axes to make more room for the data. Do so by changing the XLim property of either axes since they share the same x limit:
XL = get(a,'Xlim');
xl = XL{1}; %// here XL{1} and XL{2} are the same...[1 100]
set(a(:),'Xlim',[xl(1)-.5 xl(2)+.5])
As for the annoying tick marks at the bottom of the plot, I must say that I don't know how to remove them while keeping the axes visible.
As an alternative solution to plotyy, here is a way to obtain a good result (I think) without plotyy. The trick is to superimpose 2 axes and make both of them not visible, then set the figure's color to white and add a black rectangle surrounding the plot.
Here is the code:
clear
clc
close all
x = 1:100;
y1 = rand(size(x));
y2 = 100*rand(size(x));
H1 = area(x,y1);
%// Set the figure color to white
set(gcf,'Color','w')
%// Plot data and set different properties for each axes
A1 = gca;
A2 = axes('Position',get(A1,'Position'));
H2 = area(x,y2);
set(A2,'YAxisLocation','right','Color','none','XTickLabel',[]);
set(A2,'XLim',get(A1,'XLim'),'XTick',[],'YTick',[]);
set(A1,'XTick',[],'YTick',[]);
%// Make both axes not visible.
set(A2,'Visible','off')
set(A1,'Visible','off')
axes(A1)
%// Get axes limits
XL = get(gca,'XLim');
YL= get(gca,'YLim');
%// Create rectangle as a bounding box
rectangle('Position',[XL(1) YL(1) XL(2)-1 YL(2)],'LineWidth',5)
%//===
%// Change the data color/properties
hP = findobj('Type','patch');
set(hP(1),'FaceColor','b','FaceAlpha',.5,'EdgeColor',[0 0 0],'line','none')
set(hP(2),'FaceColor','r','FaceAlpha',.5,'EdgeColor',[0 0 0],'line','none')
And the output:
It's not perfect but hope that helps!
this is the first time that I post something on stackoverflow, so please excuse me if the post is not top quality.
I am trying to make a figure in MATLAB with some interconnected nodes arranged in a circle, and I would like to label each of these nodes (for example, 1 2 3, etc.). When I use this sample code with the "Rotation" commented out (last line), I get badly aligned text labels. What can I do to have them equidistantly placed from the node plot without having to rotate the text? Thank you all in advance! (I attach the figure that the code is generating).
%# 60-by-60 sparse adjacency matrix
A = bucky();
N = length(A);![enter image description here][1]
%# x/y coordinates of nodes in a circular layout
r = 1;
theta = linspace(0,2*pi,N+1)'; theta(end) = [];
xy = r .* [cos(theta) sin(theta)];
%# labels of nodes
txt = cellstr(num2str((1:N)','%02d'));
%# show nodes and edges
figure(123)
line(xy(:,1), xy(:,2), 'LineStyle','none', ...
'Marker','.', 'MarkerSize',15, 'Color','g')
hold on
gplot(A, xy, 'b-')
axis([-1 1 -1 1]); axis equal off
hold off
%# show node labels
h = text(xy(:,1).*1.05, xy(:,2).*1.05, txt, 'FontSize',8);
%set(h, {'Rotation'},num2cell(theta*180/pi))
I think the issue is your text is aligned left. You put your text boxes at all the points around the circle plus some radial offset. This causes your text labels to appear off center with the left alignment. If you change the text alignment to center this will alleviate this issue.
The following is an example edit to your code you can use to achieve what you want. Note, I also increased the radial offset a little too.
%# show node labels
h = text(xy(:,1).*1.08, xy(:,2).*1.08, txt, 'FontSize',8);
set(h, {'HorizontalAlignment'},{'center'})
I am plotting a bar chart in Matlab. I would like to know if it is possible to base the colours of the bars based on a simple condition? I would like all the positive bars to be say blue and the negative ones to be red. If this is possible can you please tell me how I can going about doing this in MATLAB?
Yes, it's possible, see this solution on MATLAB Central.
Here's some example code extracted from this. The third column of the data is used to determine which colour to apply to each bar. In your case, you just need to check whether each value is positive or negative and change the colour accordingly.
data = [.142 3 1;.156 5 1;.191 2 0;.251 4 0];
%First column is the sorted value
%Second column is the index for the YTickLabel
%Third column is the reaction direction
% Data(1,3) = 1 -> bar in red
% Data(1,3) = 0 -> bar in blue
% For each bar, check direction and change bar colour
H = data(:, 1);
N = numel(H);
for i=1:N
h = bar(i, H(i));
if i == 1, hold on, end
if data(i, 3) == 1
col = 'r';
else
col = 'b';
end
set(h, 'FaceColor', col)
end
Alternatively, you could include your conditions (here data>0 and data<0) as follows:
data = rand(8,1) - .5;
figure(1);
clf;
hold on;
bar(data.*(data>0), 'b');
bar(data.*(data<0), 'r');
I'm plotting a figure that is a grid of colors/shades, based on the values from a 4x5 matrix.
The x-axis and y-axis tick labels are set using text from a cell array.
The y-axis tick labels exist at 2 levels,
% y ticks, 2 levels
ylabelnames = {'team1','set1';'team1','set2';'team2','set1';'team2','set2'};
I'd like the y-axis tick labels to either
1) span 2 lines, so that they match the 2 lines of text being overlaid in the squares of the plot, i.e. 'team#' on the first line and 'set#' on the second line of each row of the imagesc grid, or
2) rotate the label 'team1' to span across the first 2 rows and rotate label 'team2' to span across the last 2 rows, to not repeat the use of 'team1' 'team2' in the labeling.
My entire code:
%% Plot
Matrix = rand(4,5);
Matrix2 = rand(4,5);
% y ticks, 2 levels
ylabelnames = {'team1','set1';'team1','set2';'team2','set1';'team2','set2'};
xlabelnames = {'group1','group2','group3','group4','group5'};
sigfig = 2;
spacer = '\n';
% Font sizes
plotFontSize = 8; labelFontSize = 8; plotWidth = 500; plotLength = 300;
imagesc(abs(Matrix))
colormap('gray')
colormap(flipud(colormap))
caxis([0 2])
for rows = 1:size(Matrix,1)
for columns = 1:size(Matrix,2)
if abs(Matrix2(rows,columns))<= 0.5 % Show 2nd values less than 0.5
num = Matrix2(rows,columns);
num = vpa(num,sigfig);
num = ['= ' char(num)];
rval = sprintf('%0.2g', Matrix(rows,columns));
message = sprintf([ 'val= ' rval spacer 'val2' num '' ]);
text(columns,rows, message,'HorizontalAlignment','center',...
'FontSize',plotFontSize,'FontName','Times New Roman');
end
end
end
% Put on tick labels
set(gca,'Ticklength', [0 0],'YTick',1:size(Matrix),'XTick',1:length(xlabelnames),...
'YTickLabel',ylabelnames,'XTickLabel',xlabelnames,...
'FontSize',labelFontSize,'FontName','Times New Roman')
If you run this, you'll see that only the first column of the y-labels are used, even though there's plenty of space to fit 2 rows of text per imagesc row.
I did think of a terrible hack way, which is to use
ylabel('team1 team2')
with the huge spaces between labels to spread them out evenly between the y rows, but that's not convenient if I were to increase the size of my matrix, so I'd prefer not doing it that way.
Is there any way to achieve the multi-leveled y tick labeling that I require?
Thanks!
In your example I'd use the text function. For example you can just add:
text(-0.05,1.5,'team1','HorizontalAlignment','center','Rotation',90 );
text(-0.05,3.5,'team2','HorizontalAlignment','center','Rotation',90 );
and see the outcome. The trick is to understand that each "pixel" (or imagesc cell element) is also a unit of the function's 'text' x and y inputs (and also of the ticks if you don't have different scaling), so to go between the first and second blocks use y=1.5 or y=3.5 etc...
to go outside the image on the left use a negative x value (x=-0.05) etc. Read more on text properties here...