Can I change lines from numeric to datetime without deleting them?

I have an already generated plot and I want to change the X data for all lines on the plot to some other data that happens to be datetimes (the original X values were numeric). When I do this, the lines on the primary Y seem to get converted ok, but when I have lines on a right Y, I am getting errors.
This simple script should demonstrate the issue:
% Create a figure
f = figure;
ax = axes(f);
% Initialize the right Y
yyaxis(ax,'right');
% Plot something on the left
yyaxis(ax,'left');
line1 = plot(ax,1:10,1:10);
% Plot something on the right
yyaxis(ax,'right')
line2 = plot(ax,1:10,(1:10).^2);
% Make the left Y active again
yyaxis(ax,'left');
% Change to datetime
% Some new x data
newX = datetime(2022,9,1:10);
% Set the XAxis ruler to be a datetimeruler
ax.XAxis = matlab.graphics.axis.decorator.DatetimeRuler;
drawnow;
line1.XData = newX;
line2.XData = newX;
Line 1 will update as expected, but Line 2 still wants numeric data for some reason. I have already tried setting the XAxis after switching the active Y axis as well and that doesn't seem to change anything.
Is there a better/different way to easily switch between numeric and datetime data for all lines on a plot?
I know I could delete the lines and run plot again, but the real use case has quite a few lines and the size of the data is pretty large so not having to redraw them would be ideal.

9 Comments

I have tried using the same metamorphosis with the RH active as well. I get the same results.
After some more testing, it seems like setting the XAxis explicitly seems to cause the issue. Even if I delete the lines and redraw them, if I set the XAxis to a different ruler rather than letting plot do it, I still get errors:
Error:
% Create a figure
f = figure;
ax = axes(f);
% Initialize the right Y
yyaxis(ax,'right');
% Plot something on the left
yyaxis(ax,'left');
line1 = plot(ax,1:10,1:10);
% Plot something on the right
yyaxis(ax,'right')
line2 = plot(ax,1:10,(1:10).^2);
% Make the left Y active again
yyaxis(ax,'left');
% Change to datetime
% Some new x data
newX = datetime(2022,9,1:10);
% Delete the exisitng lines
delete(line1);
delete(line2);
% Set the XAxis ruler to be a datetimeruler
ax.XAxis = matlab.graphics.axis.decorator.DatetimeRuler;
% Redraw the lines
yyaxis(ax,'left');
line1 = plot(ax,newX,1:10);
% Plot something on the right
yyaxis(ax,'right')
line2 = plot(ax,newX,(1:10).^2);
Works:
% Create a figure
f = figure;
ax = axes(f);
% Initialize the right Y
yyaxis(ax,'right');
% Plot something on the left
yyaxis(ax,'left');
line1 = plot(ax,1:10,1:10);
% Plot something on the right
yyaxis(ax,'right')
line2 = plot(ax,1:10,(1:10).^2);
% Make the left Y active again
yyaxis(ax,'left');
% Change to datetime
% Some new x data
newX = datetime(2022,9,1:10);
% Delete the exisitng lines
delete(line1);
delete(line2);
%%%%% This was the line that caused the error!!!
% Set the XAxis ruler to be a datetimeruler
% ax.XAxis = matlab.graphics.axis.decorator.DatetimeRuler;
% Redraw the lines
yyaxis(ax,'left');
line1 = plot(ax,newX,1:10);
% Plot something on the right
yyaxis(ax,'right')
line2 = plot(ax,newX,(1:10).^2);
I have not had much luck with overwriting an existing axes with a different kind of ruler.
Matt Butts , your initial solution would work fine with regular axes but yyaxis doesn't play by the same rules. I'm glad I stumbled upon this. In the mean time, your workaround to recreate the lines should work. You could store the YData in a variable and then reassign it to the new lines with datetime x-values. If you need to find the line objects, use findobj(ax,'type','line').
Consider adding an answer below with your workaround!
@Adam Danz: would it not be better to store the handles to the plotted lines in some organized fashion rather than looking for lines among everything plotted?
@Bjorn Gustavsson, absolutely storing handles is better than finding them but the OP's question starts, "I have an already generated plot..." so I assume the OP didn't generate the graphics objects and therefore can't store the handles.
@Adam Danz So if I understand your comment correctly, there is no way to do this when using yyaxis without deleting the lines and then using plot to recreate them.
@Bjorn Gustavsson I do have the handles to all of the lines; I was trying to avoid redrawing graphics to save some of the overhead and instead just change the XData.
@Matt Butts are you generating the lines with numeric xdata and then changing the xdata to datetime? If so, then why not just generate the lines with datetime data to begin with? Why do you need to change the xdata instead of just specifying the desired xdata to begin with?
@Adam Danz This is part of an app that I am distributing to users and part of the app lets them choose from a bunch of channels in their data what they want to use for X and Y. The user may change their mind and want to select a different X.
If the options are mixed classes that require different axes types (e.g., numeric, categorical, datetime, duration), then it's better to just replace the line objects with new ones. Unless you're dealing with 100s of lines, the processing time won't differ noticeably between those two options.

Sign in to comment.

Answers (0)

Categories

Find more on Creating, Deleting, and Querying Graphics Objects in Help Center and File Exchange

Products

Release

R2021b

Asked:

on 21 Sep 2022

Commented:

on 22 Sep 2022

Community Treasure Hunt

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

Start Hunting!