Matlab Image and Plot with Unexpected Flip - matlab

In the examples below, there are some obvious code differences in each case, but I don't understand how they would change the orientation of the image or the plot, as shown in each case.
The original image has a size of 407 x 813 x 3.
For the data in the contour, X ranges from -180 to +175, Y ranges from -85 to +85
For the image, I am trying to fit it so that X ranges from -180 to +180, Y ranges from -90 to +90. So the image covers a slightly wider geographic range than the image does.
I have a contour plot of some geographic data. It plots like this, and looks like I expect it to look:
The code to plot this looks is
figure (1);
contour(X, Y, dec0Mat,contoursAt, 'ShowText','on', 'LineWidth', 2);
colormap('Gray');
I can plot the image by itself, and it looks ok:
using this code:
figure (99)
imagesc([-180 180], [-90 90], worldMap);
But when I try to combine the two, I get this:
Using this code:
figure (1);
image([-180 180], [-90 90], worldMap);
hold on
title('Declination at elev = 0 km');
contour(X, Y, dec0Mat,contoursAt, 'ShowText','on', 'LineWidth', 2);
colormap('Gray');
In this case the map looks right, but the contour is flipped vertically.
In another case, I get this:
Using this code:
figure (3);
hold on
title('Declination at elev = 30 km');
imagesc([-180 180], [-90 90], worldMap);
contour(X, Y, dec30Mat,contoursAt, 'ShowText','on', 'LineWidth', 2);
colormap('Gray');
In this case the map is flipped vertically and the contour is plotted right.
Going by the Matlab documentation for imagesc, it says:
imagesc(x,y,C) displays C as an image and specifies the bounds of the
x- and y-axis with vectors x and y. If x(1) > x(2) or y(1) > y(2), the
image is flipped left-right or up-down, respectively. If x and y are
scalars, the image is translated to the specified location (x,y) such
that the upper left corner of the image starts at (x,y).
I highlighted what might be relevant for an image being flipped, but neither seems to be the case here and wouldn't explain the inconsistency where is is flipped in one case and not the other.

The explanation is that the imagesc command, like image, sets the 'Ydir' axis property to 'reverse'.
When called with C or X,Y,C, image sets the axes limits to tightly enclose the image, sets the axes YDir property to 'reverse', and sets the axes View property to [0 90].
This means that the vertical axis values increase from the top of the axis to the bottom.
Now you can compare the two cases:
If you run the contourf command by itself, you have the "normal" axis mode, with vertical axis values increasing from the bottom of the axis to the top. The vertical axis labelling in your first figure reflects that.
If you plot the image with imagesc and run contour on the same figure, the vertical axis is first flipped by imagesc. The subsequent contour command operates on a flipped vertical axis, and plots accordingly. That's why the contour lines are vertically flipped with respect to case 1.
Note that the combined figure obtained in case 2 is correct. If you "visually" combined the first two images of your question (which were obtained from calling imagesc and countour independently) it would be wrong, because they have different vertical axes.

This is not exactly a problem of rotation, but more a problem of vertical flip.
If you look carefully at your first two plots, you'll see that the vertical scales are flipped, so if you combine your two plots directly (whatever the way) you will end up with what you observe, i.e. one plot that is flipped with respect to the other.
I would suggest to flip the contour plot before superposition:
hold on
image([-180 180], [-90 90], worldMap);
title('Declination at elev = 0 km');
contour(X, Y, flipud(dec0Mat), contoursAt, 'ShowText','on', 'LineWidth', 2);
colormap('Gray');
or
hold on
image([-180 180], [-90 90], worldMap);
title('Declination at elev = 0 km');
contour(X, -Y, dec0Mat, contoursAt, 'ShowText','on', 'LineWidth', 2);
colormap('Gray');
Best,

Related

Matlab: Plot a line over an image plot

I want to plot a line plot on top of an image plot in Matlab
First I plot the image data
figure(1); clf;
imagesc(t); colorbar
hold on;
axis tight
and then the line plot
line(ysum,y,'Color','red')
hold off;
The line plot however deletes the image and sets the background to white.
How can I plot on top of the image?
Your code isn't wrong, but it is not a minimal reproducible example, since you haven't defined t, y, ysum. When you call imagesc(t) the rows and columns will be the indices of t. In other words, it is the same as calling imagesc([1, size(t,2)], [1, size(t,1)], t). If t is small (say 10 x 10) but the elements of y,ysum are large (e.g. > 1000) then the 10 x 10 image will still be there, but it will be squished into the corner. Almost invisible.
So you need to make sure that the range of y, ysum, t line up. A quick work-around:
xidx = [min(ysum), max(ysum)];
yidx = [min(y), max(y)];
imagesc(xidx, yidx, t);

Matlab - adapt xlim and ylim to remove white margin with surfc

I get an issue about the plot of 2d map of a surface with temperature (represented by color). The solution that I plot here is symmetric.
array x represents the array containing the temperature on (sizex,sizey) map size. In my code, sizex = 256 and sizey = 96.
I plot with the following code snippet :
surfc(x);
shading interp;
view([0,0,1]);
hc=colorbar;
set(hc,'position',[0.932 0.3 0.02 0.6]);
caxis([-10 10]);
xlabel('x domain');
ylabel('y domain');
zlabel('temperature');
xlim([0 sizex+2]);
ylim([0 sizey+2]);
and I get the following figure :
As you can see in the script, I added "2" to sizex and sizey to fill a white exterior margin.
If I don't add these values, i.e doing :
xlim([0 sizex]);
ylim([0 sizey]);
Then, I get the following figure :
And you can notice that parts of solution on right and upper sides are not displayed (rather hidden).
You can also see that even on the first figure above (like also for the second figure) (with adding "2" to xlim and ylim), it remains a slight white margin on bottom and I don't know how to remove it.
More precisely, I would like to fit exactly the dimensions of plot with dimensions of the grid data, i.e having temperature over 256x96 size without having margins.
First of all you defined sizex and sizey wrong. I copied your data from pastebin and size(x) yields [258,98] and not [256,96].
Now the other problem that you have is the following: You feed a 2D-Matrix x to surfc. Now what the command does, is putting the value x(1,1) at position (1,1) in the plot. If you don't want these "white borders" you need to put the value at position (0,0) instead. You can achieve that by feeding three matrices X,Y,Z to the surfc-command. You can genereate the matrices as follows:
[X,Y]=meshgrid(0:size(x,2)-1,0:size(x,1)-1);
Z=x;
surfc(X,Y,Z);
% From here on your regular code starts
shading interp;
view([0,0,1]);
hc=colorbar;
set(hc,'position',[0.932 0.3 0.02 0.6]);
caxis([-10 10]);
xlabel('x domain');
ylabel('y domain');
zlabel('temperature');
You should not need to define the limits of the plot now. In case you still need to, use this:
xlim([0,size(x,2)-1]);
ylim([0,size(x,1)-1]);

Matlab - axes properties

How to make x-axis and y-axis cross at origin and label the axes in both sides, i.e 'xlabel' in +ve x-axis and 'xlabel' in -ve x-axis and similarly for 'ylabel'.
You can use the function drawaxis taken here to position the x- and y- axis. Then you can add text annotations as labels. The function does have a few limitations but that's very easy to use.
clear
clc
close all
x = -10:10;
y = rand(size(x))-.5;
plot(x,y)
%// Here the axes cross at(0,0)
drawaxis(gca, 'x', 0,'y',0)
text(5,-.05,'+ axis','HorizontalAlignment','center')
text(-5,-.05,'- axis','HorizontalAlignment','center')
Output:

Plot vector (or arc) onto a rose plot. MATLAB

I have two datasets. One detailing a list of angles (which I am plotting onto a rose plot):
angles
-0.8481065519
0.0367932161
2.6273740453
...
n
The other, detailing directional statistics from this group of angles:
angle,error
-0.848106563,0.8452778824
Where angle essentially defines the directional mean, and error the circular variance, essentially an error bar either side of the angle
I have thus far plotted a rose histogram using the set of angles, as such:
h = rose(angles,36)
I would like to create a plot of the directional statistic angle (it does not need a length/magnitude - just to the edge of the circle plot) with the error around it.
As an example:
I added the lines by hand in Matlab. If possible it would be good to perhaps have shading within the arc too. Alternatively, (and possibly preferred) would be to have just a sliver above the rose plot bins (so it doesn't cover the data) with a centre line (showing the angle and shading surrounding for the error.
Thanks in advance.
How about this?
%// Data
angles = 2*pi*.8*randn(1,1e4);
angle = -0.848106563;
error = 0.8452778824;
%// Plot rose
rose(angles, 36);
axis image %// make axis square
hold on
%// Plot mean
a = axis;
a = a(2); %// size of axis
plot([0 cos(angle)*a], [0 sin(angle)*a], 'r')
%// Plot error as many shaded triangles that compose a circular wedge
t = linspace(-error/2+angle,error/2+angle,100); %// increase "100" if needed
for k = 1:numel(t)-1
h = patch([0 cos(t(k))*a cos(t(k+1))*a 0], ...
[0 sin(t(k))*a sin(t(k+1))*a 0], [.5 0 0], 'edgecolor', 'none');
%// change color [.5 0 0] to something else if desired. Note also alpha
set(h,'Facealpha',.3) %// make transparent
end
%// Place rose on top by rearranging order of axis children
ch = get(gca,'children');
set(gca,'children',[ch(2:end); ch(1)]);
For this to work, you need to use a figure renderer capable of transparency. So you may need to adjust the figure's renderer property.

How can I use a vector to label my x axis using imagesc? [duplicate]

I'm trying to change the image axis labels with some latitude/longitude but I can't find how to do it. I tried some basic commands like:
imagesc(data)
axis(meshgrid([-180:20:180],[-90:20:90]))
colorbar
but these expression appeared:
imagesc(data),axis(meshgrid([-180:20:180],[-90:20:90])), colorbar
Operands to the || and && operators must be convertible to logical scalar
values.
Error in axis>allAxes (line 448)
result = all(ishghandle(h)) && ...
Error in axis (line 57)
if ~isempty(varargin) && allAxes(varargin{1}).
Can anybody help me? FYI, my image axis labels are the data order (from 0 to N).
My desired results is an image looks like a world map, with graticule/grid lines as the axes. It should be looked like this:
From your question I infer that you want to set the x-axis labels from -180 to 180, and the y-axis labels from -90 to 90. To do this, you should change the XTickLabel and YTickLabel properties of the axis object (note that you'll also need to adjust the number of ticks in each axis by modifying the XTick and YTick properties accordingly).
So, assuming that your image is stored in the matrix data and you display it with imagesc(data), here's how to change the tick labels in the x-axis to be from -180 to 180:
xticklabels = -180:20:180;
xticks = linspace(1, size(data, 2), numel(xticklabels));
set(gca, 'XTick', xticks, 'XTickLabel', xticklabels)
Similarly, here's how to change the tick labels in the y-axis to be from -90 to 90:
yticklabels = -90:20:90;
yticks = linspace(1, size(data, 1), numel(yticklabels));
set(gca, 'YTick', yticks, 'YTickLabel', flipud(yticklabels(:)))
This is what it should look like:
Can't say I fully understand what you mean, so here goes. To add a label to an axis use xlabel and ylabel, for example:
xlabel('time [sec]'); ylabel('Amplitude');
To change the labels of the axis ticks, use something like:
plot(1:4)
set(gca,'Xtick',1:4,'XTickLabel',{'a', 'b', 'c', 'd'})
Working with imagesc you may want to add this line:
set(gca, 'YDir', 'reverse');
this will set the numbers on the Ticks growing for the bottom left corner...