forked from nplot/nplot
-
Notifications
You must be signed in to change notification settings - Fork 0
/
plot1d.m
165 lines (138 loc) · 7.36 KB
/
plot1d.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
function linespecs = plot1d(list,varargin)
% function linespecs = plot1d(list,axdim,axhandle)
% list: Data in liststruct format, may be cell array
% varargin may contain:
% 'axdim', dim: Which coordinate dimension to use as x-axis
% 'axhandle', handle: given in case previous axes are to be used
% (can be array to use multiple when list is cell array)
% 'offset', yoff: Offset on y-axis
% 'plotstyle', pstyle: (default) plotstyle string. (Overrides .plotstyle field in list)
% Returns:
% linespecs: Cell array of plotstyles
% - saves a struct plotdataset in guidata of current figure for each data set:
% .x, .y, .dy, .axhandle, .plothandle, (.mlist), (.tlist), (.legendtext)
% - updates the data cursor display of the figure window appropriately
% P. Steffens, 06/2016
if ~iscell(list), m = list; clear list; list{1}=m; clear m; end % ensure cell array
plottype={'ob','or','ok','og','oc','fb','fr','fk','fg','fc'};
multipleaxes = false;
linespecs = {};
% interpret varargin
axdim = readinput('axdim',varargin); if isempty(axdim), axdim = 1; end
yoffset = readinput('offset',varargin); if isempty(yoffset), yoffset = 0; end
pstyle = readinput('plotstyle',varargin);
axhandle = readinput('axhandle',varargin);
if isempty(axhandle)
figure; axhandle = axes;
else
if numel(axhandle)>1
if numel(axhandle) == length(list), multipleaxes = true;
else fprintf('Error: Number of axes handles not consistent with number of plots.\n'); return; end
if ~all(ishandle(axhandle)), fprintf('Error: invalid axes.\n'); return; end
end
end
set(gcf,'currentaxes',axhandle(1)); hold on; box on
% get guidata from figure
figdata = guidata(gca);
if ~isfield(figdata,'plotdataset'), figdata.plotdataset = {}; end
dcount = length(figdata.plotdataset);
if ~isempty(pstyle) && ischar(pstyle) && (any(pstyle=='|') || any(pstyle==','))
% if pstyle given like 'style1|style2,..' convert this to cell array {'style1','style2',..}
pstyle = strsplit(pstyle,{'|',','});
end
%Loop over datasets
for num = 1:length(list)
if isempty(list{num}) || isempty(list{num}.coordlist), continue; end
if multipleaxes, set(gcf,'currentaxes',axhandle(num)); hold on; box on; end % set axis, if necessary
% set plotstyle
if ~isempty(pstyle), list{num}.plotstyle=pstyle; end
% use custom plotstyle if string. (Can also be struct, see below)
if isfield(list{num},'plotstyle') && ischar(list{num}.plotstyle), linespec = list{num}.plotstyle;
else linespec = plottype{mod(num-1+dcount,length(plottype))+1}; % default
end
if strfind(linespec,'f'), linespec(linespec=='f') = 'o'; filled = true; else filled=false; end
linespecs{num}=linespec; %#ok<AGROW>
% Plot
h = errorbar(list{num}.coordlist(:,axdim), list{num}.valuelist(:,1)+yoffset, list{num}.valuelist(:,2), linespec , ...
'MarkerFaceColor', 'auto', 'MarkerSize',8, 'Linewidth',1.3);
if filled, set(h,'MarkerfaceColor',get(h,'Color')); else set(h,'MarkerfaceColor','none'); end
% if plotstyle is struct, set custom properties now
if isfield(list{num},'plotstyle') && isstruct(list{num}.plotstyle)
pfields = fieldnames(list{num}.plotstyle);
for fn=1:length(pfields)
set(h, pfields{fn}, list{num}.plotstyle.(pfields{fn}));
end
end
set(h,'tag','data'); %(cursorfcn (below) looks for this)
% if any(strcmpi(varargin,'printcallback')), set([h,gca],'ButtonDownFcn',@mouseclick1); end
set(datacursormode(gcf),'UpdateFcn',@cursorfcn);
% set up structure for this data set
thisplotdata.axhandle = axhandle; % "parent" axes
thisplotdata.plothandle = h; % handle of errorbar object
thisplotdata.x = list{num}.coordlist(:,axdim);
thisplotdata.y = list{num}.valuelist(:,1);
if size(list{num}.valuelist,2)<=2, thisplotdata.dy = list{num}.valuelist(:,2); end
if isfield(list{num},'monitorlist'), thisplotdata.mlist = list{num}.monitorlist(:,1); end
if isfield(list{num},'taglist'), thisplotdata.tlist = list{num}.taglist; end
if isfield(list{num},'legend'), thisplotdata.legendtext = list{num}.legend; end
figdata.plotdataset = [ figdata.plotdataset, thisplotdata];
% Show legend
if ~any(strcmpi(varargin,'nolegend')) && isfield(list{num},'legend')
if isempty(legend(gca))
legend(h, list{num}.legend);
else % get current legend and add new entry
if verLessThan('matlab','8.4') %<R2014b
[~, ~, legobjs,text_strings]= legend(gca);
else % new syntax of Matlab legend command
ax = gca;
legobjs = findobj(ax.Children,'flat','-regexp','Displayname','\S+');
text_strings = {};
for j=1:numel(legobjs), text_strings{j} = legobjs(j).DisplayName; end %#ok<AGROW>
legobjs = legobjs(end:-1:1); text_strings = text_strings(end:-1:1);
end
legend([legobjs', h], [ text_strings, {list{num}.legend}, ]);
end
end
end
guidata(gcf, figdata);
%% Update function for data cursor
function txt = cursorfcn(~,event_obj)
% Customizes text of data tips
pos = get(event_obj,'Position');
txt = {['X: ',num2str(pos(1))], ['Y: ',num2str(pos(2))]}; % default text
if get(datacursormode(gcf),'snaptodatavertex') % try to get additional info
tar = get(event_obj,'Target'); % handle of graphics object of data tip
if ~strcmpi(get(tar,'tag'),'data'), return; end
figdata = guidata(gcf);
if ~isfield(figdata,'plotdataset'), return; end
ind = 1; l = length(figdata.plotdataset);
while ind<=l && figdata.plotdataset{ind}.plothandle ~= tar, ind=ind+1; end
if ind>l, return; end % object not found
% identify index of data point (by min. distance)
[~,npoint] = min((figdata.plotdataset{ind}.x-pos(1)).^2 + (figdata.plotdataset{ind}.y-pos(2)).^2);
if isfield(figdata.plotdataset{ind},'dy'), txt = [txt, {['dY: ',num2str(figdata.plotdataset{ind}.dy(npoint))]}]; end
if isfield(figdata.plotdataset{ind},'mlist'), txt = [txt, {['Sum Mon.: ',num2str(figdata.plotdataset{ind}.mlist(npoint))]}]; end
if isfield(figdata.plotdataset{ind},'tlist'), txt = [txt, {['Data: ',num2str(figdata.plotdataset{ind}.tlist{npoint})]}]; end
end
end
% %% Callback routine for Mouseclick in Axes
%
% function mouseclick1(src,evnt)
% % Callback for Mouseclick
% if strcmp(get(gcf,'SelectionType'),'normal')
% figdata = guidata(gca);
% cp = get(gca,'CurrentPoint');
% xmouse = cp(1,1); ymouse = cp(1,2);
% xl = xlim; yl = ylim; xr = xl(2)-xl(1); yr = yl(2)-yl(1);
% [m,npoint] = min(((figdata.clist(:,1)-xmouse)/xr).^2 + ((figdata.clist(:,2)-ymouse)/yr).^2);
% fprintf(['x=' num2str(figdata.clist(npoint,1)) ', y=' num2str(figdata.clist(npoint,2))]);
% if figdata.mlist(npoint)>0
% fprintf([', Mon=' num2str(figdata.mlist(npoint))]);
% end
% if ~isempty(figdata.tlist(npoint))
% fprintf([', Scans # ' figdata.tlist{npoint}]);
% end
% fprintf('\n');
% end
% end
end