Place annotations using axis coordinates from a date-axis
11 views (last 30 days)
Show older comments
Hello there,
I have another problem... I want to place annotations in my plot, see the figure below.
Now, as one can see the x-axis uses datenum-numbers. How can I position the annotations using these coordinates? Each of the vertical lines should be placed at 00:00 (12PM), the dates in the center of the resulting box.
This is how far I got:
clc
clear all
close all
% Get the data
filepath=''; % Note: Im realen File gibt es natürlich einen Pfad
fprintf('Path: %s\n', filepath)
fprintf('\nLoad totaldev ...\n')
totaldev = xlsread(strcat(filepath,'totaldev.xlsx'));
fprintf(' ...done!\nLoad plant_load ...')
plant_load = xlsread(strcat(filepath,'load.xlsx'));
fprintf(' ...done!\n')
data=[plant_load(:,1),plant_load(:,2),totaldev(:,2)];
data(:,1)=x2mdate(data(:,1));
fprintf('Prepare data ...\n')
% Remove values below 0 and above 100 (plant load is 0% to 100%
data(any(data(:,2)<0,2),:)=[];
data(any(data(:,2)>100,2),:)=[];
% Remove values below -100 and above 100 (error can't be more than +-100%)
data(any(data(:,3)<-100,2),:)=[];
data(any(data(:,3)>100,2),:)=[];
% Compute average of time series
% Sample rate is 2sec, so 30 values cover a minute
data_avg=[data(:,1), movavg(data(:,2),30,30), movavg(data(:,3),30,30)];
data_avg(1:30,2)=data(1:30,2);
data_avg(1:30,3)=data(1:30,3);
fprintf(' ...done!\n')
fprintf('\nCreate plot')
% Plot 'em
plot(data_avg(:,1),data_avg(:,2),data(:,1),data_avg(:,3))
NumTicks = 20;
L = get(gca,'XLim');
set(gca,'XTick',linspace(L(1),L(2),NumTicks))
datetick('x','HH:MM','keepticks','keeplimits');
The function movavg will be replaced by tomorrow. The data is as follows (example) ([Time; Data1; Data2]):
735728,605428241 80,6717800000000 11,6650710000000
735728,605451389 80,6717800000000 9,12566720000000
735728,605474537 80,1416200000000 9,24074830000000
735728,605497685 80,1416200000000 9,20919460000000
735728,605520833 80,1416200000000 9,47081590000000
735728,605543982 80,3848000000000 9,28115980000000
735728,605567130 80,3848000000000 8,55264740000000
735728,605590278 80,3848000000000 9,47107710000000
735728,605613426 80,5608400000000 9,42203640000000
735728,605636574 80,6196400000000 9,32575490000000
735728,605659722 80,6196400000000 9,25049830000000
735728,605682870 80,6998100000000 9,48914560000000
735728,605706019 80,6998100000000 9,52505890000000
735728,605729167 80,6998100000000 9,12462120000000
735728,605752315 80,1338500000000 8,44201380000000
735728,605775463 80,1338500000000 8,38791130000000
735728,605798611 79,9584800000000 8,67874090000000
735728,605821759 79,9584800000000 8,92738190000000
735728,605844908 79,5133300000000 9,50254300000000
I have no idea now how to place the annotations using the code. Since I have to plot this figure a few times I don't want to set the annotations by hand each time ...
I hope someone can help =)
Cheers from Germany
0 Comments
Accepted Answer
dpb
on 27 May 2014
Edited: dpb
on 27 May 2014
A start...basically, you just generate datenums that match the locations you want.
dt=datenum(2014,5,[10:12]); % datenums for the day tick locations
xt=repmat(dt,3,1); xt=xt(:); % and make an array of x and y locations
xt(3:3:end)=nan; % insert nan to break lines between locations
yt=repmat([-0.95 -1.1 nan]',3,1); % to draw the lines at those locations (*)
hl=line(xt,yt,'color','r','clipping','off'); % lines; made red so stand out
% write the text.
ht=text(dt+0.5,-1.2*ones(size(dt)),datestr(dt,'mm.dd.yyyy'),'horizontal','center','fontsize',8);
(*) The "trick" in generating the arrays is that of inserting the NaN between the line segments to avoid drawing from the end point of the first the diagonal to the first point of the second, etc., ...
On the location for the datestr, I didn't create the other vector of locations; just used the midnight location plus 0.5 day to get noon next day for demo purposes of the idea. That works correctly for the full days in the middle, otherwise you take the average of the two datenums for the beginning and end of the partial days at the two ends.
Also, in my playing here I used a ylim(-1 1)] and the y locations for the line and the text are based on that value--you'll want to retrieve the lower y limit and adjust based on it for your case. Alternatively, you can switch to normalized coordinates relative to the whole figure and retrieve the position of the axes and work out locations therefrom. annotation works on those coordinates so if choose to go that route instead you'll have to use those. I tend to just use the axes and smudge a little. Note to get the line to show outside the axes, must set its 'clipping' property to 'off'
4 Comments
dpb
on 28 May 2014
You're welcome...hacking on handle graphics is both frustrating and (sometimes) rewarding... :)
Just a couple of comments --
...reading your newest date vector I was a bit confused...
It wasn't intended as actual code but the outline of the values you need as being the quarter-day under the first full day, then the N full days at midnight/zero-hundred hours plus the half-day for noon, and finally the last day plus the quarter. Looks like you did get there, though, although I probably should have explained it wasn't intended to be code, just a map.
One problem I'm not sure of how it worked in the end, but it would be cleaner if the x and y vectors for the line were (using yt for example) were written as
yt=repmat([-16 -21 NaN].',3,1);
instead so the line segment is drawn and then there's the NaN breaking the line before the next grouping of three. That you had the NaN first in row was, I think, why you missed one earlier. You can get away w/ removing the last NaN as superfluous but it's simpler to just leave it.
Anyway, your end result does look very nice...
More Answers (0)
See Also
Categories
Find more on Annotations 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!