Plotting with small time values in MATLAB
2 Ansichten (letzte 30 Tage)
Ältere Kommentare anzeigen
I am struggling with a code to plot time in x axis. I have variable ‘TimeValues1’ which is in ‘datetime’ format and ‘PhysicalValues1’ in ‘single’ format with same row as that of TimeValues1 and 3 columns. What I want is TimeValues1 in x axis and first column of PhysicalValues1 in yaxis.
When I do so, I am getting a plot which is shown in Figure 1. But if I plot first column of PhysicalValues1 alone, I am getting a plot as shown in Figure 2 and if I plot with a dummy variable given by ‘linspace(1, 2,length(PhysicalValues1))’, I am getting the plot similar to that of Figure.
![](https://www.mathworks.com/matlabcentral/answers/uploaded_files/1063950/image.png)
Edit1 (forgot to add the code):
clear;close all;clc;
load('PhysicalValues1.mat')
load('TimeValues1.mat')
figure('units','normalized','outerposition',[0 0 1 1])
subplot(311)
plot(TimeValues1,PhysicalValues1(:,1),'LineWidth',1.25,'Color','k')
axis tight
ax=gca;ax.YMinorTick='on';ax.XColor='k';ax.YColor='k';ax.LineWidth=1.2;
title('Figure 1')
subplot(312)
plot(PhysicalValues1(:,1),'LineWidth',1.25,'Color','k')
axis tight
ax=gca;ax.YMinorTick='on';ax.XColor='k';ax.YColor='k';ax.LineWidth=1.2;
title('Figure 2')
subplot(313)
plot(linspace(1, 2,length(PhysicalValues1)),PhysicalValues1(:,1),'LineWidth',1.25,'Color','k')
axis tight
ax=gca;ax.YMinorTick='on';ax.XColor='k';ax.YColor='k';ax.LineWidth=1.2;
title('Figure 3')
I gather that the problem lies in TimeValues1. But why is it that I am getting apparently different plot? Any hint will be greatly appreciated.
I am using MATLAB 2021b and the MATLAB variables are attached with this question.
Thank you.
1 Kommentar
dpb
am 13 Jul. 2022
Show us the actual code lines you used to create the plots -- it isn't perfectly clear from just the verbal description, but if you use
plot(TimeValues1,PhysicalValues1(:,1))
the x axis will be in calendar time units if the time is a datetime
But, if as you describe it is so that you then plotted just
plot(PhysicalValues1(:,1))
then MATLAB just plots the values against the ordinal number of the observation -- which would be 1:numel(TimeValues1) and is what the plot axes appears to be (the image is too smal for old eyes to read)
In the last case, you got what you asked for as well; the scale was created to go from 1 to 2 with the number of points...and that's what MATLAB did.
What is it that you think is a problem? Looks to be what would be expected...
Antworten (2)
dpb
am 13 Jul. 2022
Bearbeitet: dpb
am 13 Jul. 2022
AM coffee apparently hadn't yet kicked in...dawned upon me later what you're undobutedly looking for is
t=TimeValues1-TimeValues1(1)); % turn into duration array from initial time
hL=plot(t,PhysicalValues1(:,1)); % plot first column, save line handle for later mods, maybe???
2 Kommentare
dpb
am 14 Jul. 2022
Well, no, I don't understand the Q? you have at all -- why would you NOT think the two would be different???
The first is plotted against the elapsed time from the beginning of the data trace; the second again just against the ordinal number of the observation.
The axes aren't scaled to make the two traces the identical length because without specifically setting the limits, the internal logic scales the limits to provide round, "pretty" x tick marks.
OH.
The problem is you don't have enough precision in the input time vector to differentiate between values -- observe the following:
>> T=TimeValues1;
>> T.Format
ans =
'dd-MMM-uuuu HH:mm:ss.SSS'
>> T.Format=strcat(T.Format,'SSSSSS');
>> T(1:10)
ans =
10×1 datetime array
26-Dec-2019 18:08:25.213000000
26-Dec-2019 18:08:25.213000000
26-Dec-2019 18:08:25.213000000
26-Dec-2019 18:08:25.213000000
26-Dec-2019 18:08:25.213000000
26-Dec-2019 18:08:25.213000000
26-Dec-2019 18:08:25.213000000
26-Dec-2019 18:08:25.213000000
26-Dec-2019 18:08:25.213000000
26-Dec-2019 18:08:25.213000000
>>
Even adding enough "S" to the end of the format to show nanoseconds shows the actual input values were truncated at the millisecond level.
>> uT=unique(T);
>> numel(T)/numel(uT)
ans =
149.62
>>
shows there are ~150X as many time values as there are unique times -- hence, when you plot agains time or the duration, 150 points are drawn at the same location on the x axis -- but if you plot against the ordinal number, then they're all spread out at incremental values -- with 64K points, however, that's still rouughly 32X the number of points as there are pixels on a typical monitor in the horizontal direction, so a bunch of the points will still be plotted on top of each other, either way, just not quite as many.
You either have to record the timestamps at much finer resolution, or, if you know what the actual sample rate was (and it was fixed), you can forget about the recorded times and just use that sample rate times the number of points to compute the actual time.
dpb
am 14 Jul. 2022
Bearbeitet: dpb
am 14 Jul. 2022
As above notes, there isn't sufficient precision in the time vector to differentiate between roughly 150 consecutive measurements -- looking at the overall time from beginning to end and the number of samples, one can estimate the sampling rate as
>> t(end)/numel(t)*1E6
ans =
duration
00:06.668094087
>>
That's close enough that one might conjecture the sampling frequency was 150 kHz --
>> t(end)
ans =
duration
00:00.436000000
>> numel(t)/150E3
ans =
0.43591
>>
The rounded 0.436 seconds in the time vector is quite close to the 0.43591 value you would get if assumed 150 kHa sample rate.
Does this match up to your actual collection rate I presume?
ADDENDUM
The duration class isn't very flexible in its output display formatting -- it has a very limited set of options; for signal processing use, you're probably better off just using a double numeric array instead. I've submitted enhancement requests on the topic but none have been implemented so far.
2 Kommentare
dpb
am 14 Jul. 2022
Bearbeitet: dpb
am 14 Jul. 2022
Actually, I forgot about the "numeric" display option -- you can specify "s" and the duration will then show up as numeric values in the existing command window format. This is better than trying to use the limited range of digital display formats, but is still lacking convenience in there not being scaling factors for msec, nsec, etc., so your case would look something like
t(1:10)=seconds((0:9)/150E3);
>> t(1:10)
ans =
10×1 duration array
0 sec
6.6667e-06 sec
1.3333e-05 sec
2e-05 sec
2.6667e-05 sec
3.3333e-05 sec
4e-05 sec
4.6667e-05 sec
5.3333e-05 sec
6e-05 sec
>>
plot() would, however, just display the seconds on the axis using this, but don't believe any way to set the scaling other than by physically multiplying by the desired factor.
It can be done down to nanosecond resolution, but you would have to record the timestamps themselves with sufficient resolution to use the technique as these data were taken. Whether that's a possibility with whatever it was isn't knowable from the information given so far.
If this did satisfy the underlying Q?, then Accept the answer so others will know there is a resolution if for no other reason...
Siehe auch
Kategorien
Mehr zu Calendar finden Sie in Help Center und File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!