Plotting global sea surface temperatures on MATLAB - matlab

I am trying to plot global sea surface temperatures for April 2015 on MATLAB using JMA's dataset in GRiB format. I have also installed the nctoolbox and m_map toolboxes.
Below is my code:
!wget http://ds.data.jma.go.jp/tcc/tcc/products/elnino/cobesst/gpvdata/2010-2019/sst201504.grb
nc=ncgeodataset('sst201504.grb')
nc.variables %to check the variable names in this file
lat=double('lat');
lon=double('lon');
sst=double(squeeze('Water_temperature_depth_below_sea'));
m_proj('miller','lat',[min(lat(:)) max(lat(:))],...'lon',[min(lon(:)) max(lon(:))])
m_pcolor(lon,lat,sst);
However, when I used the m-pcolor function, the following error message is generated:
Error using pcolor (line 53)
Color data input must be a matrix.
Error in m_pcolor (line 53)
[h]=pcolor(X,Y,data,varargin{:});
I am still able to plot the coastline and gridlines using the following code though, but without the coloured temperature anomalies:
m_coast;
m_grid;
Did I miss out anything in my code? lat and lon are 1x3 double arrays, while sst is a 1x33 double array.

I think the problem lies in improperly defining the variables and array sizes, as the array sizes of lat, lon and sst do not match each other correctly. It has to do with the file problem though, as evident from the fact that the array sizes for lat and lon are too small to display gridded global SST data.

I don't know if this will solve all your difficulties, but double('lat') is converting the string "lat" to a double. It will always be [108 97 116]. Remove the quotes like so: double(lat).
Similarly for double(squeeze('Water_temperature_depth_below_sea')). You want to convert the variable to double, not the variable's name.

Related

MATLAB for loop through columns to plot multiple lines

I need your help again :). I'm trying to plot multiple lines for a very large dataset. To start easier, I divided the dataset to get a TABLE in Matlab that contains 6 columns, with the first column representing the date that I want on my x-axis. Now I want to plot the other columns (and in the original file are a lot more than 6 columns) on the y axis, using a for loop. I tried the following, with no success:
hold on
for i=2:1:6
plot(Doldenstock(:,1), Doldenstock(:,i));
end
hold off
As I understand this, this code would do exactly what I want for columns 2,3,4,5,6. However, I always get the same error code:
Error using tabular/plot
Too many input arguments.
Error in Plotting_bogeo (line 6)
plot(Doldenstock(:,1), Doldenstock(:,i));
Now, I don't know if maybe for loops like this don't work for tabes but only for arrays?
Thanks for your help in advance!
Cheers,
Tamara
The function plot(x) expect x to be a scalar, a vector, or a matrix. But in your case the input is a table, because accessing a table with parentheses return a table, which is not supported.
If you read the doc "how to access data in a table" you will figure out that you need to use curly brace {} to extract the raw data (in your case a 1D matrix).
So use:
plot(T{:,1},T{:,2})

extract data from a matrix, maintaining NaNs as NaNs matlab

I have a dataset called 'data' of size 106*103*100. I am extracting a portion of the dataset for further analysis based on its geographical position using latitudes and longitudes and naming the extracted data 'testdata'). 'data' contains a mixture of both numbers and NaNs.
The data I want to extract lies within the latitudinal and longitudinal bounds of ylat_south=44,ylat_north=55,xlon_west=16 and xlon_east=30;
The matrix of latitudes is called: final_lat (106*103);
The matrix of longitudes is called: final_lon (106*103);
This is what I have to extract the data:
for i=1:size(data,3);
testdata(:,:,i)=+(final_lat>=ylat_south & final_lat<=ylat_north &
final_lon>=xlon_west & final_lon<=xlon_east).*data(:,:,i);
end
The code I have works (i.e. I end up with testdata of size 106*103*100), except, when testdata is written out, any cells that contained a NaN in 'data' are being written as a zero is the new 'testdata' matrix'. I know I could do this is a loop, with an if statement, but I am trying to keep the code as efficient as possible.
Any suggestions appreciated.

NACA Airfoil Matlab questions

I got an obstacle in generating an NACA Airfoil graph. Here is the code:
% NACA 6414%
clc
clear
format compact
m1=input('Please enter one digit number for maxi camber line:')
p1=input('Please enter one digit number for distance of m and chordline:')
t1=input('Please enter two digit number for thickness of airfoil:')
m=m1*0.01;
p=p1*0.1;
t=t1*0.01;
x1=[0:0.01:p];
x2=[p:0.01:1];
x=[x1,x2]
yc1=(m*(2*p*x1-x1.^2))/(p^2);
yc2=(m/(1-p)^2)*((1-2*p)+2*p*x2-x2.^2);
yt=(t/0.2)*(0.2969*sqrt(x)-0.1260*x-0.3516*x.^2+0.2843*x.^3-0.1015*x.^4)
yc=[yc1,yc2]
ang1=(atan((m/p^2)*(2*p-2*x1)))*180/pi
ang2=(atan((m/(1-p)^2)*(2*p-2*x2)))*180/pi
ang=[ang1,ang2]
xu=x-yt.*sin(ang)
yu=yc+yt.*cos(ang)
xl=x+yt.*sin(ang)
yl=yc-yt.*cos(ang)
xplot=[xu,xl]
yplot=[yu,yl]
plot(xplot,yplot)
Instead of generating an normal airfoil graph, it comes with an very weird graph which contains many circles on the picture. Can any one help me figure out how to fix that?
Thanks.
Here's the problem, I suspect:
ang1=(atan((m/p^2)*(2*p-2*x1)))*180/pi
ang2=(atan((m/(1-p)^2)*(2*p-2*x2)))*180/pi
ang=[ang1,ang2]
xu=x-yt.*sin(ang)
yu=yc+yt.*cos(ang)
xl=x+yt.*sin(ang)
yl=yc-yt.*cos(ang)
The functions sin and cos expect an input in radians. The output of atan is also in radians, but you're converting it to degrees, which means that the output in xu, yu, etc, which you later plot will be wrong. Try to avoid conversion unless you really need the angles in degrees. Alternatively, you could use the other forms of these functions (sind, cosd, atand, etc) and keep everything in degrees throughout.

Error " Index exceeds Matrix dimensions"

I am trying to read an excel 2003 file which consist of 62 columns and 2000 rows and then draw 2d dendrogram from 2000 pattern of 2 categories of a data as my plot in matlab. When I run the script, it gives me the above error. I don't know why. Anybody has any idea why I have the above error?
My data is here:
http://rapidshare.com/files/383549074/data.xls
Please delete the 2001 column if you want to use the data for testing.
and my code is here:
% Script file: cluster_2d_data.m
d=2000; n1=22; n2=40; N=62
Data=xlsread('data.xls','A1:BJ2000');
X=Data';
R=1:2000;
C=1:2;
clustergram(X,'Pdist','euclidean','Linkage','complete','Dimension',2,...
'ROWLABELS',R,'COLUMNLABELS',C,'Dendrogram',{'color',5})
After the xlsread statement you should get a 2000x62 double matrix Data. Then you transpose it and assign to X, so X is 62x2000 matrix. In the clustergram vectors for the properties RowLabels and ColumnLabels are supposed to match the size of your Data, but you pass a 2000-length vector as RowLabels and 2-length vector as ColumnLabels. This might cause the error.
What version of MATLAB are you using? It looks like pretty old, since you have clustergram as function, but in later versions of Bioinformatic Toolbox it was redesigned as object. In R2010a your code would generate
"ROWLABELS size does not match data"
but I'm not sure what it would be in old version.
Try to remove RowLabels and ColumnLabels, as well as other properties. Do you still get the error?

Plotting data on time (date) axis

I have data like this:
22.10.1980. 100
25.10.1980. 120
26.10.1980. 12
(only much more of it, and for each date, several independent measurements on the right).
Now, this is probably trivial, but I've never done anything like it in MATLAB, and am having problems finding similar examples online. I need to plot the data on a time/showing dates axis (x axis), with all dates inside (so, 23. and 24. as well ... for which I don't have measurements).
How can I get dates to show up on a plot axis?
It seems like it might be the best to use datetick.
Usage: datetick('x') or datetick('x', dateformat) with the available formats as explained in the documentation.
Assuming your data file has the format given above, you could use textscan to read the data:
fid = fopen('data.txt','rt');
C = textscan(fid,'%s %s %s %d','Delimiter','.','CollectOutput',1);
fclose(fid);
The first cell of C will contain an N-by-3 cell array of strings (the parts of the date) and the second cell of C will contain an N-by-1 vector of the data measurements. You can create a date number for each measurement by first concatenating the 3 smaller strings into one date string and then using the datenum function:
t = datenum(strcat(C{1}(:,3),'-',C{1}(:,2),'-',C{1}(:,1)));
data = C{2};
Once you have a vector of date numbers t to go with your vector of measurements data, you can then plot them:
plot(t,data,'*'); %# Plot the points as asterisks
Now, you can change the x-axis labels to show the actual dates. One option is to use the function datetick, an easy and elegant solution given in steven's answer. Another option is to use the function datestr to create the labels yourself, then modify the XTick and XTickLabel properties of the current axes:
xpts = min(t):max(t); %# Make a full vector, filling in missing dates
set(gca,'XTick',xpts,'XTickLabel',datestr(xpts)); %# Set axes properties
NOTE: Whichever option you choose for changing the x-axis labels to date strings, you may run into trouble with the labels overlapping each other if the tick marks are too close together. You could fix this by reducing or repositioning the tick marks along the x-axis (by changing the XTick property) or by adjusting the axes FontSize property. If you wanted to rotate the labels to make them fit, you would have to erase the labels and create new rotated text objects for them. The following submission on The MathWorks File Exchange does just that:
Rotate Tick Label by Andrew Bliss
With datenum you can convert any string date into numerical format based on the date format symbols (see help datestr).
For example all this leads to the same numerical date representation:
datenum('15/05/2009 21:22','dd/mm/yyyy HH:MM');
datenum('15.05.2009 21:22','dd.mm.yyyy HH:MM');
datenum('21-22 15.05.2009','HH-MM dd.mm.yyyy');
datenum('21-22 05/15.2009','HH-MM mm/dd.yyyy');
...
The nice thing is that you can pass cell array (output from textscan) or char array directly to datenum and it will output numeric date array.
Datetick is a good option, as well as datetick2, which can be found here: MATLAB Central
Datetick2 allows panning and zooming, with adjustments to the time labels, depending on how far you're zoomed in.
I'm not sure about the dd.mm.yyyy format - you could use regexp or strrep to change the decimals to dashes if neccessary.
You can use datenum to convert the dates to a numbers, and plot the data as usual. lets say you put your dates vector in the variable called x.
Now, you can use
set(gca, 'xtick',x(1:10:end));
set(gca, 'xticklabel',datestr(x(1:10:end));
to set the ticks on the x axis.