I'd like to use imagesc to plot a matrix with distance on y axis, z in colorbar, and datetime on x axis. Y and Z are in the matrix (12 x 500) and datetime is in seperate vector t (12 x 1).
I have the following code but the datetime that shows up on the x axis is January 1, January 2, ... (from 1 - 12).
If I add t, the imagesc doesn't show up.
How can I plot the 12 x 500 matrix and plot t as x axis?
figure
imagesc(D', 'Interpolation', 'bilinear');
set(gca, 'YDir', 'normal');
colorbar
set(gca, 'XTick', t);
datetick('x', 'mmmm dd HH:MM', 'keepticks')

1 commentaire

Siegmund
Siegmund le 13 Sep 2022
In addition, any suggestion on how to extent the interval between the ticks? t shows intervals of 15min. It would be nice if it would only show the day and with a time interval of 6 hours...

Connectez-vous pour commenter.

 Réponse acceptée

Walter Roberson
Walter Roberson le 13 Sep 2022
Unfortunately, it is not supported to use datatime() objects for imagesc axes.
datetick() is not for datetime() objects: it is for the older serial date numbers, which is numerically days and fractions of a day since a particular starting point.
If your t is datetime() objects then use
tnum = datenum(t);
imagesc(D', 'Interpolation', 'bilinear', 'XData', tnum);
set(gca, 'YDir', 'normal')
colorbar
xticks(tnum);
datetick('x', 'mmmm dd HH:MM', 'keepticks')

8 commentaires

Siegmund
Siegmund le 13 Sep 2022
That worked perfect! Thanks a lot
Siegmund
Siegmund le 13 Sep 2022
In addition, any suggestion on how to extent the interval between the ticks? t shows intervals of 15min. It would be nice if it would only show the day and with a time interval of 6 hours...
The x-axis with datenum is no different than any other numeric axes other than the values are scaled to represent the given date as @Walter Roberson described.
You don't give us enough to go on to know what the t vector actually is, but you can create an arbitrary set of x-tick values.
However, it doesn't make sense there are 15 min intervals in t if it is only 12 elements -- that would only be 3 hours total length.
You can try
datetick('x','dd-HH')
to display the day and hours; see <datetick> and follow links to formats to see all the codes available.
You can set an arbitrary time vector for the ticks by
tk=datenum(2022,1,[1:12].');
xticks(tk)
duplicates the Jan1, Jan2, ... 12-length. The input arguments to <datenum> are year,month,day,hour,min,sec so you can build whatever pattern you wish.
Siegmund
Siegmund le 13 Sep 2022
Yes, true. I just used a subset here. t represents data every 15min between 6h and 18h over weeks of data. Ideally, I’d have a break between 18h-6h and only show the data during the day, with then the day as ticklabel.
Thanks for clarifying it.
dpb
dpb le 13 Sep 2022
Unfortunately, Matlab graphics doesn't implement broken/segmented axes -- you can introduce NaN values to not show data out of a vector, but the axes are continuous and unbroken; the next date/time value will show up where it belongs in relation to the previous; if there's 12-hr missing, that will (as I'm sure you're now aware) just show up as a big gap.
I know of only two basic ways to work around the problem --
  1. Use multiple axes such as tiledlayout or subplot and have each segment be represented on a separate axis of its own. Such solutions have issues of placement of spacing between axes and such as to make them appear to be one plot instead of many. Doable in theory, a lot of work... or,
  2. Adjust the time data of each subsequent set of data by the end time of the previous shown segment plus a smidge...the downside of this solution is that while the data are then drawn contiguously, the time axis is artificial and the effective time labels will have to be written independently of the x-tick values so datetick doesn't help any more.
It's another of those big holes in the graphics functions that's existed since forever....you're only supposed to have well-behaved data that doesn't have breaks in it, apparently.
Walter Roberson
Walter Roberson le 13 Sep 2022
There is a File Exchange Contribution https://www.mathworks.com/matlabcentral/fileexchange/3683-breakxaxis . It works by adjusting the tick positions and labels -- so for example datatips would treat the axes as continuous.
Siegmund
Siegmund le 15 Sep 2022
Modifié(e) : Siegmund le 15 Sep 2022
If I'd add the missing timesteps in the matrix as NaN, the plot would look like we wanted?
I tried the following but that's not entirely working yet.
Times = datetime(t(:),'ConvertFrom','datenum');
WP = timetable(Times, D);
tnum = retime(WP, 'regular', 'mean', 'TimeStep', minutes(15));
N = height(tnum);
for i = 1:N
if any(isnan(tnum(:,i)))
D(i,:)=NaN;
end
end
imagesc(D', 'Interpolation', 'bilinear', 'XData', tnum);
set(gca, 'YDir', 'normal')
colorbar
xticks(tnum);
datetick('x', 'mmmm dd HH:MM', 'keepticks')
...
N = height(tnum);
for i = 1:N
if any(isnan(tnum(:,i)))
D(i,:)=NaN;
end
end
...
in MATLAB is simply written as
D(any(isnan(tnum(:,i))),:)=NaN;
using vectorized logical addressing.
But, you don't need to do that, anyways, if either x or y variable is not finite the HG2 routines won't show anything for those locations so simply the bad x value will be sufficient.
However, once you created the timetable, the time variable is a datetime and so it will be NAT and you'll need isnat instead of isnan
BUT, there's still the problem that visually this will just create bands on the axes in those locations; it won't collapse the axis; it will still be continuous over the full time span.
It takes one of the ways of adjusting the axes or the times themselves to create the effect desired. I've not tried the FEX submission linked to, in the past the one I tried had some warts; don't recall if the same or not; even if was those may have been fixed by now so give it a shot as the simplest route forward until, at least, it's shown not to be adequate.

Connectez-vous pour commenter.

Plus de réponses (0)

Produits

Version

R2020b

Community Treasure Hunt

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

Start Hunting!

Translated by