imagesc or equivalent with datetime as x axis.
27 views (last 30 days)
Show older comments
Chris Heintz
on 24 Jan 2022
Commented: Benjamin Kraus
on 21 Sep 2023
I'd like to use imagesc (or some other function that produces similar output) to plot some data with a numerical y axis and datetime x axis. I'd strontly prefer not to use datenums for the x axis, because the axis doesn't update when zoomed, the datatips aren't fomatted nicely (like they are for plots with datetime as the x axis), and subsequent plots don't work with datetime as the x axis.
Example:
clear; close all;
times = datetime('now') + hours(0:1:50);
yvals = 0:5:100;
colors=randn(size(yvals,2),size(times,2)) + yvals';
im=imagesc(times,yvals,colors);
set(gca,'YDir','normal');
pcolor seems to work, but the offsetting is undesirable (my data is "face centered", not "vertex centered"), as are the gridlines.
I've tried various things like setting the x axis to a DatetimeRuler and this method using duration with no success.
Thanks!
3 Comments
Walter Roberson
on 29 Jan 2022
I do not think you would be able to do it with linkaxes(), but you might be able to use a listener to listen for a resize or pan event.
I seem to recall that there is a way to coerce an axes to be a particular type, but I have forgotten all of the details.
Accepted Answer
Benjamin Kraus
on 18 Jan 2023
Edited: Benjamin Kraus
on 20 Sep 2023
If you are using MATLAB R2023b or newer:
Starting in MATLAB R2023b, you can now work with images on datetime rulers natively.
times = datetime('now') + hours(0:1:50);
yvals = 0:5:100;
colors=randn(size(yvals,2),size(times,2)) + yvals';
im=imagesc(times,yvals,colors);
set(gca,'YDir','normal');
If you are using MATLAB older than R2023b, continue reading for the old solution:
It is a bit of a hack, but another option (if you want to continue using imagesc) is to "preconfigure" the axes for datetime using a command (such as plot) that does support datetime, then leverage ruler2num to convert your data into double for passing to imagesc.
One reason for ruler2num is to allow you to add objects that don't (yet) support datetime natively to be added to an axes that has existing datetime data. This is just leveraging that approach, but then deleting the "other data".
Note that in order to use this approach:
- You have to "preconfigure" the axes before any other objects are added to the axes. In other words: The first object added to the axes is used to set-up the axes to support datetime data. If there are existing objects and the axes is not already configure for datetime data, adding datetime data will throw an error.
- You need to use hold on because otherwise the first thing the imagesc command will do is reset the axes configuration back to the default (numeric) configuration. This means that you need to manually set any axes properties that are normally set by the imagesc command.
For example:
figure
times = datetime('now') + hours(0:1:50);
yvals = 0:5:100;
colors=randn(size(yvals,2),size(times,2)) + yvals';
% This command will configure the axes for use with datetime
% Then delete the line created by the plot command.
delete(plot(times(1), yvals(1)));
% Now hold is required, because otherwise the axes will be reset by the
% image command.
hold on
% Now you can convert from datetime to numerics using ruler2num
x = ruler2num(times, gca().XAxis);
% Now pass the double data to imagesc.
im=imagesc(x,yvals,colors);
% Finally, because hold was on, you need to manually set the limits (which
% is normally done for you by imagesc) and turn on the box. I ommited
% flipping the YDir becuse you seem to want that set to 'normal' anyway.
axis tight
box on
hold off
I'm aware this workaround isn't ideal, and I'm working on native support for datetime data in the imagesc command, so this workaround should not be necessary.
3 Comments
Benjamin Kraus
on 21 Sep 2023
It is hard for me to keep track (given that we were almost done with R2023b when R2023a shipped for customers), but I did just confirm that this feature was implemented for R2023b. Maybe you are thinking of the prerelease?
More Answers (3)
KSSV
on 25 Jan 2022
times = datetime('now') + hours(0:1:50);
yvals = 0:5:100;
colors=randn(size(yvals,2),size(times,2)) + yvals';
im=imagesc(colors);
set(gca,'YDir','normal');
xticks = 1:5:50; %adjust as appropriate, positive integers only
xlabels = cellstr(times(xticks) ); %time labels
% xlabels = num2str( ( T(xticks)) ); % you don't need this
set(gca, 'XTick',xticks, 'XTickLabel', xlabels);
xtickangle(45)
Eric Delgado
on 5 Apr 2022
@Chris Heintz, "mesh function" is the answer that you are looking for.
times = datetime('now') + hours(0:1:50);
yvals = 0:5:100;
colors = randn(size(yvals,2),size(times,2)) + yvals';
fig = figure;
ax = axes(fig);
[X, Y] = meshgrid(times, yvals);
mesh(ax, X, Y, colors, 'FaceColor', 'interp')
view(ax, 0,90);
set(ax, 'XLim', [times(1), times(end)], 'YLim' , [yvals(1), yvals(end)])
1 Comment
Martin Ryba
on 7 Jul 2022
imagesc interprets the values of the pixels to be at the centers of each coordinate, whereas surf/mesh/pcolor/etc. interpret them to be at the edges of the coordinates and truncate bits appropriately. It's not what most of us want.
See Also
Categories
Find more on Graphics Performance in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!