MATLAB Answers

contouring of 3 vectors

58 views (last 30 days)
Jacqueline Chrabot
Jacqueline Chrabot on 30 Jan 2021
Commented: Walter Roberson on 31 Jan 2021
I'm trying to make a contour plot using three vectors. I want to contour chlorophyll as a function of depth and time. Each vector is a different length and so I keep getting an error when using interp2. I've also tried using griddata and I'm still getting errors, As well as TriScatterInterp. Can some help me de-bug one of the three ways.
x=dntime
x1=min(dntime)
y=depth_corrected
y1=min(depth_corrected)
%[X,Y]=meshgrid(x,y); %gives the depth/time mesh grid
%chloro
%Z=interp2(X,Y,chloro,x1,y1); %2d interpolation
F=TriScatteredInterp(dntime(:),depth_corrected(:),chloro(:));
dielcycle=F(dntime,depth_corrected);
contour(X,Y,Z)
% x=dntime
% y=depth_corrected
% xq=1:16
% yq=0:0.3500:max(depth_corrected) % depth range
% z=chloro
%vq=griddata(x,y,z,xq,yq) %not gonna work until you change time columns
  2 Comments
Jacqueline Chrabot
Jacqueline Chrabot on 30 Jan 2021
Attached is the data. I indexed them so they are there own arrays. From left to right is dntime (date and time) in the same column, then the depth, and then, the chloro measurement taken at that depth and time. I want to contour the chloro with depth being the y and date/time being on the x axis.

Sign in to comment.

Answers (3)

Star Strider
Star Strider on 30 Jan 2021
I was able to import these and get an actual datetime array out of the first column:
T1 = readtable('Data.csv');
T1.Var1 = cellfun(@(x)datetime(x,'InputFormat','''''MM-dd-yyyy HH:mm:ss.SSSS''''', 'Format','MM-dd-yyyy HH:mm:ss.SSSS'),T1.Var1);
[Ut,ia,ix] = unique(T1.Var1,'stable');
and an overview of the file:
Segments = diff(ia);
GS = groupsummary(T1,'Var1');
producing:
GS =
16×2 table
Var1 GroupCount
________________________ __________
08-16-2016 02:01:01.0000 1170
08-16-2016 03:56:28.0000 497
08-16-2016 05:56:36.0000 374
08-16-2016 07:57:30.0000 491
08-16-2016 10:02:23.0000 532
08-16-2016 11:59:36.0000 325
08-16-2016 11:59:37.0000 412
08-17-2016 01:56:15.0000 763
08-17-2016 02:03:10.0000 335
08-17-2016 03:59:40.0000 684
08-17-2016 04:00:04.0000 452
08-17-2016 04:53:44.0000 358
08-17-2016 05:58:19.0000 324
08-17-2016 08:00:14.0000 380
08-17-2016 09:59:44.0000 326
08-17-2016 10:56:04.0000 347
The problem is that since there are unequal numbers of each time, using reshape or griddata or any other function to create uniform arrays that contour would be able to use is simply not possible as the data currently exists.
This works for ‘TimeVector’:
TimeVector = linspace(min(T1.Var1), max(T1.Var1), 2000);
however this:
Cols23 = interp1(T1.Var1, T1{:,2:3}, TimeVector(:));
throws the expected error:
Sample points must be unique and sorted in ascending order.
I have no idea what to suggest.
  2 Comments
Star Strider
Star Strider on 30 Jan 2021
I couldn’t make the delimiters work using character arrays, the reason I went with cellfun. Using string representations in the detectImportOptions customisation is definitely the only usable approach here. I’ll keep that in mind.
I agree that the data are not organised in a way that makes contour an option.

Sign in to comment.


Cris LaPierre
Cris LaPierre on 30 Jan 2021
Edited: Cris LaPierre on 30 Jan 2021
I found myself bored, so played some more.
Challenges (not an exhaustive list)
  • varying number of samples for a given time stamp
  • no simple way to resample the data
  • datetimes are not a valid input for some of the obvious functions, including contour
  • data is not sorted
  • inconsistent values of depth
  • contour requires V to be a matrix, where rows correspond to depth and columns correspond to date.
After some playing around, I got something working. Key points are
  1. Obtain one value for each datetime and depth combination. I used groupsummary for this. A side benefit is that it returns a sorted table of increasing values (no duplicates). There are often multiple chloro values for a datetime-depth combination. In this case, I elected to use the median value, though there are many possible options (min, max, mean, custom function)
  2. I created a fixed depth increment using linspace. This is used to compute new chloro values at known depths for all dates.
  3. Since there is no obvious relationship day to day, I created a new matrix (rows=depth, columns=unique datetimes) and populated each column with the corresponding chloro values, obtained using interp1 with the known depths and chloro values, and interpolating to the fixed depth values.
  4. Contour does not allow an input of datetimes. I therefore convert the datetime to a numeric value representing elapsed time in days from the first date. This was arbitrary. I could have used seconds, minutes, hours, etc. The important thing is that it be a numeric value that retains the relative spacing between the dates.
% Load the data
opts = detectImportOptions("JCData.csv");
opts.VariableNames = ["dntime","depth","chloro"];
opts.Delimiter=["'",","];
opts.ConsecutiveDelimitersRule="join";
opts.LeadingDelimitersRule="ignore";
opts=setvartype(opts,"dntime","datetime");
opts=setvaropts(opts,"dntime","InputFormat","MM-dd-yyyy HH:mm:ss.SSSS");
data = readtable("JCData.csv",opts);
% Simplify the data to a single chloro value for each unqiue dntime and depth combination
dtTbl=groupsummary(data,["dntime","depth"],"median","chloro");
% Create uniformly sampled depth
dp=linspace(min(data.depth),max(data.depth));
% Extract unique datetime values
dt = unique(dtTbl.dntime)';
% Resample chloro values at each date using uniform depth vector and interp1
V=zeros(length(dp),length(dt));
for d = 1:length(dt)
ind = dtTbl.dntime==dt(d);
V(:,d) = interp1(dtTbl.depth(ind),dtTbl.median_chloro(ind),dp);
end
% Convert datetime to numeric representation
X = days(dt-dt(1));
% plot
contour(X,dp,V)
colorbar

Jacqueline Chrabot
Jacqueline Chrabot on 30 Jan 2021
So I guess maybe this will help. I put those three arrays in a new table but maybe I should have attached the original table. There are essentially 16 tables of data I combined together using Vertcat and changed the date/time of each one of those 16 tables to the first date that was listed(so there will be 16 different dates and times) I thought this would help contour. I just wanted to contour the chlorophyll (I guess this would be z), in respect to yreverse the depth (0:max(depth_corrected)) and x the date & time. My goal is to see what the chlorophyll levels are doing in the water column. Per the original table, the chlorophyll measurements are Var11, and depth_corrected is Var7. Obviously date and time are the 1st and 2nd column. I'm kind of getting confused by all the posts as to what I need to do.
  4 Comments
Walter Roberson
Walter Roberson on 31 Jan 2021
Alternately, use griddedInterpolant or scatteredInterpolant to create an interpolated grid of output, and contour that. I seem to recall someone contributed a File Exchange contribution for that purpose.
However, the scatter plot that Cris posted on https://www.mathworks.com/matlabcentral/answers/730953-contouring-of-3-vectors?s_tid=srchtitle#comment_1296278 implies to me that you do not have enough continuity of data to be doing a contour plot.

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by