Plot a segment over an animated line in real-time with dynamic time (X) axis

3 views (last 30 days)
Hello all,
I've been struggling for a while to make this work. I have some realtime values coming from some sensors. I make forecasting based on some time-window using double exponential moving average. I want to plot the data feed in real time and every once in a while to also plot the forecast for the next N seconds. Obviously I simplified the code for the example bellow, replacing the real-time reading and writing of the values with a simple RNG, and also removed the entire forecasting part and just added a simple constant for the second plot.
N = 30; % time window
FutureTime = zeros([1,N]);
%%CREATE A FIGURE TO VISUALISE THE PLOT
f = figure('Name', 'Live Data Feed & Forecasts');
X1 = subplot(1,2,1); % There would be multiple subplots - one for every monitored parameter
X1.YGrid = 'on';
X1.YLim = [-1 2];
title('Parameter 1 Feed and Forecast');
ylabel('param 1 dimention');
xlabel('Time [hh:mm:ss]');
Line1 = animatedline('Color','r','LineWidth',2); % Animated line for the 1st subplot
All_Axes = X1; % An array containing all subplots' X axes for use with the dynamicDateTicks function
%%SET CYCLE TIME
time = now;
stopTime = '03/26 17:33'; % Run time for the cycle
count = 1; % cycle counter
while ~isequal(datestr(now,'mm/DD HH:MM'),stopTime)
time(count) = datenum(clock);
Y1 = rand; % read real-time value
addpoints(Line1,datenum(time(count)),Y1); % Plot real-time data to the respective animated line
hold on
% Update axes
X1.XLim = datenum([time(count)-seconds(N) time(count)+seconds(N)]); % Set the range of X axes to be N seconds before and after 'now'
dynamicDateTicks(All_Axes, 'HH:MM:SS') % Dynamically convert serial time to hh:mm:ss format
drawnow
%%PLOT SECOND LINE
%
% if mod(count,5)==0 % make forecast every 5 seconds for the next N seconds (starting after N sec.)
%
% Forecast_Param1(1:N) = 0.5; % tons of code here, but for cimplicity we'll take this for a constant
%
% for i=1:N % Build extended time array (N seconds into the future) from the last reading's timestamp
% FutureTime(1,i) = addtodate(time(count), i, 'second');
% end
%
% % plot the forecast on top of the live data (with transparency 80%)
% h1a = plot( FutureTime,Forecast_Param1, 'c', 'LineWidth',6, 'DisplayName',' 0.2');
% h1a.Color(4) = 0.2;
% xlim = datenum([time(count)-seconds(N) time(count)+seconds(N)]); % Set the range of X axes to be N seconds before and after 'now'
% dynamicDateTicks(All_Axes, 'HH:MM:SS') % Dynamically convert serial time to hh:mm:ss format
% drawnow
%
% end
pause(1); % Wait 1 sec for the sensors to give new values
count = count +1;
end
disp('END');
The code above works perfect as long as the second line (the plot in the cycle) is not run. The animated line moves ahead as intended and the X axis is dynamically set with the correct time window. As soon as the second plot is added the X axis stops being "dynamic" and has a constant beginning just expanding ahead. If I mark the animated line as comment and just run the plot, then again everything works fine and the X axis changes accordingly. But for the life of me, I can't make them tic together... :(
Can anyone with more experience have a look and say where might I be wrong? P.S. The dynamicDateTicks is auxiliary function by Ameya Deoras: https://www.mathworks.com/matlabcentral/fileexchange/27075-intelligent-dynamic-date-ticks

Answers (1)

Alexander Grantcharov
Alexander Grantcharov on 15 Sep 2019
Edited: Alexander Grantcharov on 15 Sep 2019
Coming back here a bit over a year later I though I'd give answeres to my own questions :) just in case anyone else needs doing the same things and is having the same struggles I had.
The script uses DynamicDateTicks by Ameya Deoras to do most of the work. Here is how I did it (I've reduced a lot of my code, and added extra comments, just to make is easier to understand):
% atm_temperature_value.Value and atm_pressure_value.Value are my live feed values acquired from the sensors
% If you want to test my code you'll have to attach these values to something else (you could use a RNG within the loop)
% The same has to be done for Forecast_Temperature and Forecast_Pressure arrays, as they are the result of the forecasting process
%% CREATE A FIGURE TO VISUALISE THE PLOTS
f = figure('Name', 'Live Data Feed', 'Position', [50 350 1800 600]);
Tx = subplot(2,5,1); % Temperature Subplot X axis
T_Line = animatedline('Color',[1.000 0.000 0.000],'LineWidth',2); % the line animating the live (main) feed of data in red
TF_Line = animatedline('Color',[1.000 0.000 0.000], 'LineWidth',4, 'DisplayName',' 0.1'); % the animated line of the second (predicted) data set (thiker red line with reduced opacity)
TF_Line.Color(4) = 0.1; % Reduced opacity for the second (prediction) line
Px = subplot(2,5,2); % Pressure Subplot
P_Line = animatedline('Color',[0.812 0.573 0.000],'LineWidth',2); % Orange
PF_Line = animatedline('Color',[0.812 0.573 0.000], 'LineWidth',4, 'DisplayName',' 0.1');
PF_Line.Color(4) = 0.1;
% An axis array for all data subplot's X axis to be updated and visualised as date time format
All_Axes = [Tx Px]; % Add all subplot's X axes to this array
% SET TIME FOR THE CYCLE (AND FINISH THE EXPERIMENT)
stopTime = '03/26 17:33'; % MM/DD Time
count = 1; % Cycle counter
while ~isequal(datestr(now,'mm/DD HH:MM'),stopTime)
%% UPDATE THE ANIMATED LINES
% Get the current time
t = datetime('now');
addpoints(T_Line,datenum(t),atm_temperature_value.Value); % Plot real-time temperature value (from the sensor) to the T_Line on Tx axis
addpoints(P_Line,datenum(t),atm_pressure_value.Value); % Plot real-time pressure value (from the sensor) to the P_Line on Px axis
%% SOME CODE HERE TO FORECAST NEXT (N) PERIOD EVERY (M) SECONDS
% Forecast_Temperature and Forecast_Pressure arrays are the result of this action
% Build extended time array (N seconds into the future)
% with 1 seconds step interval
for i=1:N
ForecastTime(1,i) = addtodate(datenum(t), i, 'second');
end
% Plot Forecasted Values
addpoints(TF_Line,ForecastTime(1,N),Forecast_Temperature(1,N)); % Adds the forcasted values to the Temperature subplot, but uses the forecasted line features.
addpoints(PF_Line,ForecastTime(1,N),Forecast_Pressure(1,N)); % The same for the Pressure.
drawnow
%% UPDATE X AXES ON ALL SUBPLOTS
Tx.XLim = datenum([t-seconds(N) t+seconds(N)]);
Px.XLim = datenum([t-seconds(N) t+seconds(N)]);
dynamicDateTicks(All_Axes, 'HH:MM:SS') % Uses the array of all X axis
drawnow
%% END ITTERATION
pause(1);
count = count +1;
end
disp('END');
I'm not sure how clear I've made this, but hopefully it is helpfull to someone. :)
Cheers!

Categories

Find more on Animation in Help Center and File Exchange

Products

Community Treasure Hunt

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

Start Hunting!