I am trying to plot an image of a matrix using the pcolor(). The matrix presents a field. (In my case a sea field! But it does not matter:) ). The problem is that when I plot the matrix using pcolor() the matrix is ploted mirrored.
An example:
A=[1 0 0;0 1 0;0 0 1];
If I plot the matrix, the cell (0,0) will be plotted not in the top left corner but in the bottom left corner.(Its obvious the start of the axes is (0,0) I understand that the function is working properly!) I know also the existence of the flipdim() functions to flip the matrix.
The problem is that the code becomes ugly if I use this approach.For example the cell(0,0) in the matrix will be appeared in cell(size(A,1),0) and everything becomes opposite! How can I face that problem in a more elegant way?
(The matrix to be printed as a terian for example and not mirrored)
Edit:
Solved using axis ij
In general, to change the direction of axis you can set YDir (or XDir) property from normal to reverse.
set(gca,'YDir','rev')
PCOLOR function produce axis with YDir set to normal. In opposite, IMAGESC's YDir is reverse by default.
Related
I'm trying to create a countourf plot with the region in the bottom left hand corner whited out. Values for the contour are provided at the corner of each rectangle in the below image and all other points on the mesh have a value of NaN.
I want to know how to stop the countourf plot from drawing the triangular section at the top right of the white square, i.e. how do I stop it from interpolating across these two values.
End game: I would like a complete white rectangle on the bottom left, not a chamfered rectangle.
You are getting that triangle because on that specific square your data looks something like:
[1 2 ;...
NaN 3]
And that is a completely valid upper right triangle to contour.
So you can interpolate your data to get more resolution and make that triangle smaller. Or you could just use patch to add a white square at the desired position.
data=rand(8);
data(1:4,1:4)=NaN;
contourf(data)
hold on;
patch([1 1 5 5],[1 5 5 1],'w')
It looks like seven squares a side, so we can set
x = 1:7;
[XX,YY] = meshgrid(x); % create x,y grid for the square
ZZ = nan(7); % create number grid for the square
ZZ(1:3,1:3)=ones(3); % set the lower 3x3 to 1
figure;
hold on % hold your plot
plot()% your contour
imagesc(XX,YY,ZZ); % Or similar
This is the outline, I can't determine what exact plotting function you need since you didn't show your code. In general, the idea is to create a grid as large as that of your contour plot, and set the lower left square to 1, thus white, leaving the rest NaN, thus not plotted.
Say I have a matrix hey 15x15. I want to plot the value of the matrix as a 2D plot for better visualization. But Matlab plots with the convention that origin is in bottom-left corner and positive x is along the left and positive y is along the up direction from origin.
but i want to make my plots such that origin is in top-left corner, +ve x is left and +ve y is down.
So i just used a slight trick.
figure
axis([0 15 -15 0]);
daspect([1,1,1])
hold on
rectangle('Position',[3,-6,2,3],...
'EdgeColor','black',...
'LineWidth',2,...
'FaceColor','cyan')
for i=1:nrows
for j=1:ncolumns
if char(hey(i,j))=='^'
text(j,-i,'^');
elseif char(hey(i,j))=='>'
text(j,-i,'>');
elseif char(hey(i,j))=='v'
text(j,-i,'v');
elseif char(hey(i,j))=='<'
text(j,-i,'<');
end
if obstacle(i,j)==1
text(j,-i,'X');
end
end
end
text(goalY,-goalX,'T');
I made the transformation (x,y)-->(y,-x). But the downside is that the axes are then numbered along y as -1 to -15. However if reader was following above, i only wanted to plot the matrix values and in matrix the y runs +ve downwards from 1 to 15 for my case.
So i want the plot to show +1 thru +15 along y with origin at top-left and x graduated as it is but the values +1 to +15 written at the top of the plot rather than below.
How to do this? In the extreme case, i am alos willing to transfer the matrix hey to another software that can do the nice plot as i want. If any of the two alternatives is possible, please give concrete steps to do it.
EDIT:
After using the helpful methods below, i still have to use a trick like plot (j,i) instead of the innocent plot(i,j). This is because for matrix (i,j) is mapped to graph plot (x,y) as x=j, y=i. Is there a similar workaround? a matrix element is (row #, column #). But in 2D matlab graph, we will denote it's position as (column #, row #). I was just guessing if there was some matlab in-built function to take care of this. like i will give it (row #, column #) but matlab will plot (column #, row #). Is there such a function?
I think axis ij does what you want:
axis ij places the coordinate system origin in the upper left corner. The i-axis is vertical, with values increasing from top to bottom. The j-axis is horizontal with values increasing from left to right.
To locate the x axis on top, change the 'XAxisLocation' of the axes to 'top' (default is 'bottom').
Example:
x = 1:10;
y = x.^2;
plot(x,y)
axis ij
set(gca,'XAxisLocation','top')
Original plot (lines 1-3 of above code):
After axis ij (line 4):
After set(gca,'XAxisLocation','top') (line 5):
If I followed correctly you are looking for the axes XAxisLocation and YDir properties. You can set them to top and reverse respectively to get the output you want. You can also set the XTick property to 1:15 to show every value from 1 to 15.
Example:
clear
clc
%// Create dummy data
[x,y] = meshgrid(1:15,1:15);
u = cos(x).*y;
v = sin(x).*y;
figure
quiver(x,y,u,v)
set(gca,'XAxisLocation','top','XTick',1:15,'YDir','reverse')
hold on
%// I changed the coordinated of the rectangle to fit with the change in
%y-axis.
rectangle('Position',[3,3,2,3],...
'EdgeColor','black',...
'LineWidth',2,...
'FaceColor','cyan')
axis([0 15 0 15])
Which gives the following:
I have been trying to figure out how to "hide" the useless part of the triangular matrix from my 3d plot in Matlab.
I have tried drawing a mesh just above that part of the graph with
'EdgeAlpha', 1, 'FaceAlpha', 1,'FaceColor','w','EdgeColor','none'
but it does not help. How should I do it instead?
The only method the semi-worked is using the color scale, but it did not work all the way, plus I need the black and white eps's, which will show the color as black even if it looks white originally...
This is my last hope ;)
Barbara
Short answer: replace "useless" data with the value nan because MATLAB does not plot data values that are nan.
Inserting nan values into the other half of the matrix should do the trick. See the example below - it's clunky, but should give the idea. I chose to multiply by nan, which I attained as shown, but there are half a dozen other things that came to mind.
% Create random data for illustration
data = tril(rand(50));
% I chose to divide by a lower triangular ones matrix (zeros above the
% diagonal) to get nan above the diagonal and ones below
nan_above_diag_ones_below = 1./tril(ones(50,50));
% Plot data with and without hiding the "useless part"
figure,
subplot(1,2,1), mesh(data), title('"useless" part shown')
subplot(1,2,2), mesh(data.*nan_above_diag_ones_below),
title('"useless" part hidden')
I am trying to plot a matrix where each element is in one out of two states. (ising model..)
Now, I would like to have one state colored and the other one white. That works using
[i,j] = find(S);
figure(gcf);
plothandle = scatter(i,j);
axis([0 nNodes+1 0 nNodes+1]);
when S holds the Spins and one state is equal to 0. (find returns a matrix of only non-zero elements)
To have a useful plot, the sizes of the markers should be 1x1 in RELATIVE coordinates. So if the whole matrix S would be in a state non-zero, everything would be colored.
However, it seems like Matlab only allows MarkerSizes in points or inches. How could I solve this?
One idea I had was, that I find out the point-size of the axes and then can easily calculate how big my markers should be. Then I would have to create a callback function if I want to zoom in and so on. Also, I have not yet found a way (without the image acq. toolbox) to find out the absolute size of my axes.
To clarify what I want: How could I plot a chessboard using a matrix with 1 for black and 0 for white fields?
For displaying data of this sort I generally prefer IMAGE or IMAGESC to PCOLOR since PCOLOR won't display the last row and column of the matrix when using faceted shading (the default). Also, IMAGE and IMAGESC flip the y axis so the image more intuitively matches what you think of when looking at a matrix (i.e. rows start from 1 at the top). You can visualize your matrix like this:
S = round(rand(20)); %# Sample 20-by-20 matrix of ones and zeroes
imagesc(S); %# Plot the image
colormap([1 1 1; 0 0 0]); %# Set the colormap to show white (zero elements) and
%# black (non-zero elements)
And here's a sample image:
Just as a suggestion, you can try using pcolor instead of `scatter' Example:
pcolor(hadamard(20))
colormap(gray(2))
axis ij
axis square
If I explain why, this might make more sense
I have a logical matrix (103x3488) output of a photo of a measuring staff having been run through edge detect (1=edge, 0=noedge). Aim- to calculate the distance in pixels between the graduations on the staff. Problem, staff sags in the middle.
Idea: User inputs co-ordinates (using ginput or something) of each end of staff and the midpoint of the sag, then if the edges between these points can be extracted into arrays I can easily find the locations of the edges.
Any way of extracting an array from a matrix in this manner?
Also open to other ideas, only been using matlab for a month, so most functions are unknown to me.
edit:
Link to image
It shows a small area of the matrix, so in this example 1 and 2 are the points I want to sample between, and I'd want to return the points that occur along the red line.
Cheers
Try this
dat=imread('83zlP.png');
figure(1)
pcolor(double(dat))
shading flat
axis equal
% get the line ends
gi=floor(ginput(2))
x=gi(:,1);
y=gi(:,2);
xl=min(x):max(x); % line pixel x coords
yl=floor(interp1(x,y,xl)); % line pixel y coords
pdat=nan(length(xl),1);
for i=1:length(xl)
pdat(i)=dat(yl(i),xl(i));
end
figure(2)
plot(1:length(xl),pdat)
peaks=find(pdat>40); % threshhold for peak detection
bigpeak=peaks(diff(peaks)>10); % threshold for selecting only edge of peak
hold all
plot(xl(bigpeak),pdat(bigpeak),'x')
meanspacex=mean(diff(xl(bigpeak)));
meanspacey=mean(diff(yl(bigpeak)));
meanspace=sqrt(meanspacex^2+meanspacey^2);
The matrix pdat gives the pixels along the line you have selected. The meanspace is edge spacing in pixel units. The thresholds might need fiddling with, depending on the image.
After seeing the image, I'm not sure where the "sagging" you're referring to is taking place. The image is rotated, but you can fix that using imrotate. The degree to which it needs to be rotated should be easy enough; just input the coordinates A and B and use the inverse tangent to find the angle offset from 0 degrees.
Regarding the points, once it's aligned straight, all you need to do is specify a row in the image matrix (it would be a 1 x 3448 vector) and use find to get non-zero vector indexes. As the rotate function may have interpolated the pixels somewhat, you may get more than one index per "line", but they'll be identifiable as being consecutive numbers, and you can just average them to get an approximate value.