Plotting with datetime in App Designer

25 views (last 30 days)
Matt
Matt on 23 Apr 2020
Edited: Benjamin Kraus on 29 Apr 2020
I am having a problem plotting data against a datetime object in an app created in App Designer. I started a new app to eliminate as many sources of error as possible, so it's very bare bones. A timetable is loaded from a .mat file via the app. That timetable contains the numeric variable and the datetime object as Time. The Time in the timetable has a timezone of 'Etc/UTC', with times from 11:30 - 13:30. I have the following components:
  • A uiaxes component for the plot
  • A button to command the plot creation
  • A button to change the timezone to 'America/New_York'
  • A button to change the timezone back to 'Etc/UTC'
  • A button to clear the axes
  • A text display to show the first element of the datetime object to verify the time before plotting.
If I click the button to create the plot after the data is loaded, it is created as expected, with times from 11:30 - 13:30. If I then click the button to change the timezone to 'America/New_York', Time(1) is displayed in the text display as 07:30, as expected. If I click the plot button, the plot does not change. This is why I added the "clear axes" button, just to be sure the plot is being redrawn. If I click the clear axes button, the axes object clears and the scale on the x-axis becomes the full day over which the datetime object spans. If I click the plot button again, the same plot appears with times from 11:30 - 13:30, even though the times in the timetable are from 07:30 - 09:30. If I restart the app, change the timezone to 'America/New_York' before plotting, then plot, the TIme on the x-axis correctly displays from 07:30 - 09:30. If I clear the axes and change the timezone to 'Etc/UTC' with the other button and then plot, the times on the x-axis are still from 07:30 - 09:30, even though they are 11:30 - 13:30 in the variable.
Am I missing something obvious here?
To be clear, what I am doing in the app is equivalent to the following from the command line or an m-file.
figure;
plot(Time,Var1);
Time is shown on the plot from 11:30 - 13:30, which matches the values in the variable Time, which have a timezone of "Etc/UTC'. I then type the following to change the timezone:
Time.TimeZone = 'America/New_York';
The contents of the Time variable are shifted as expected to 07:30 - 09:30. I then generate a new plot on the same axes.
plot(Time,Var1);
Time is shown from 07:30 - 09:30.
I can't upload the app, but here is the code from the app.
properties (Access = private)
loadedTimetable
end
% Callbacks that handle component events
methods (Access = private)
% Code that executes after component creation
function startupFcn(app)
inputStruct = load('C:\temp\test.mat','data');
app.loadedTimetable = inputStruct.data;
clear inputStruct;
end
% Button pushed function: PlotButton
function PlotButtonPushed(app, event)
plot(app.UIAxes,app.loadedTimetable.Time,app.loadedTimetable.Var1);
end
% Button pushed function: ChangeTimezonetoUTCButton
function ChangeTimezonetoUTCButtonPushed(app, event)
app.loadedTimetable.Time.TimeZone = 'Etc/UTC';
app.Time1EditField.Value = string(app.loadedTimetable.Time(1));
end
% Button pushed function: ChangeTimezonetoNYButton
function ChangeTimezonetoNYButtonPushed(app, event)
app.loadedTimetable.Time.TimeZone = 'America/New_York';
app.Time1EditField.Value = string(app.loadedTimetable.Time(1));
end
% Button pushed function: ClearaxesButton
function ClearaxesButtonPushed(app, event)
app.UIAxes.cla;
end
end
It seems like I'm missing something simple, but I can't see it. I even put a breakpoint in at the "plot" line, went to the command line and ran:
figure; plot(app.loadedTimetable.Time,app.loadedTimetable.Var1);
It plotted time correctly each time, while the app designer code plotted it incorrectly when I continued after the breakpoint.
Any suggestions are appreciated. Thank you.
  4 Comments
Matt
Matt on 23 Apr 2020
I did some additional investigating. I tried changing the clear axes button function from this:
function ClearaxesButtonPushed(app, event)
app.UIAxes.cla;
end
to this:
function ClearaxesButtonPushed(app, event)
plot(app.UIAxes,app.loadedTimetable.Var1,app.loadedTimetable.Var1);
app.UIAxes.cla;
end
I did this in an attempt to "clear" the x-axis of the datetime scale, for what that's worth. If I click the plot button after starting the app, then the clear axes button, the following error appears: Values plotted against x-axis must be datetime values. To create datetime values, use the DATETIME function.
If I cilck the clear axes button after starting the app, no error appears. If I do this from the command line:
figure;
plot(Time,Var1);
plot(Var1,Var1);
The figure shows the plots as expected, with the second plot command producing a plot that overwrites the first plot. So there appears to be a problem with plotting on a uiaxes object when using App Designer. Why am I unable to overwrite a plot with new data if the original data was a datetime object? I'm not sure if this is directly related to my original problem, but it may provide a clue. Is there a way to clear the axes object completely each time I make a plot? That's obviously what I was trying to do with the cla command, but I'm hoping there is something that "clears more" so I run the plot command again with a modified datetime object.
Matt
Matt on 23 Apr 2020
I found a workaround. Adding the 'reset' property with cla "clears" the axes object so that I can plot datetime objects correctly. I just added that before the plot command. That shouldn't be necessary, from what I can tell, so it seems like there might be a bug.
app.UIAxes.cla('reset');

Sign in to comment.

Answers (1)

Benjamin Kraus
Benjamin Kraus on 29 Apr 2020
Edited: Benjamin Kraus on 29 Apr 2020
I suspect the issue you are running into is the default reset behavior of UIAxes.
By default, the plot command calls newplot. The behavior of newplot depends on the value of the NextPlot property, which is different on regular axes vs. UIAxes. What this means is that by default the plot command will completely reset a regular axes, but will only delete the children of a UIAxes (but preserve most UIAxes properties). This was done so that you can configure the UIAxes when designing your app, and those properties are not lost when you first plot.
For example:
ax = axes;
ax.Color = 'yellow';
ap1 = plot(ax, 1:10);
ap2 = plot(ax, 1:10);
ux = uiaxes;
ux.Color = 'yellow';
up1 = plot(ux, 1:10);
up2 = plot(ux, 1:10);
With the axes above, the color will be reset when you call plot, but with the UIAxes the color will not be reset. In both cases the lines created by the first plot command will be deleted by the second plot command.
The fix for UIAxes is to set the NextPlot property:
ux = uiaxes;
ux.NextPlot = 'replace';
ux.Color = 'yellow';
up1 = plot(ux, 1:10);
up2 = plot(ux, 1:10);
This will cause the plot command (or the cla command) to reset the UIAxes. Note, this will reset most of the UIAxes properties, including the Title, XLabel, grid lines, etc.
At the moment there is no way to selectively reset just the ruler without resetting the entire axes/UIAxes.

Categories

Find more on Graphics Performance in Help Center and File Exchange

Products


Release

R2019a

Community Treasure Hunt

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

Start Hunting!