1 | % fa_zoomer([server]) |
---|
2 | % |
---|
3 | % Investigate and zoom into archive data for the last day. |
---|
4 | function fa_zoomer(server) |
---|
5 | % h is used to store all persistent state that is not part of the generated |
---|
6 | % data. |
---|
7 | h = {}; |
---|
8 | |
---|
9 | if nargin == 0 |
---|
10 | h.server = 'ac7b727-pc1'; |
---|
11 | else |
---|
12 | h.server = server; |
---|
13 | end |
---|
14 | |
---|
15 | % Create figure with the standard toolbar but no menubar |
---|
16 | fig = figure('MenuBar', 'none', 'Toolbar', 'figure', ... |
---|
17 | 'Position', [0 0 900 600]); |
---|
18 | global data; |
---|
19 | data = {}; |
---|
20 | |
---|
21 | % Create the controls. |
---|
22 | global h_pos; |
---|
23 | h_pos = 10; |
---|
24 | h.bpm_list = control('edit', '4', 60, 'List of BPM FA ids'); |
---|
25 | h.bpm_name_list = control('popup', ... |
---|
26 | dev2tangodev('BPMx',family2dev('BPMx')), 130, ... |
---|
27 | 'Choose decimated data type to display', 'Value', 1, ... |
---|
28 | 'Callback', protect(@bpm_name_callback)); |
---|
29 | control('pushbutton', 'Back', 40, 'Return to previous zoom', ... |
---|
30 | 'Callback', protect(@back_callback)); |
---|
31 | control('pushbutton', 'Full', 40, 'View entire archive history', ... |
---|
32 | 'Callback', protect(@full_archive_callback)); |
---|
33 | control('pushbutton', '24h', 40, 'View last 24 hours', ... |
---|
34 | 'Callback', protect(@last_day_callback)); |
---|
35 | control('pushbutton', 'Zoom', 60, 'Update zoomed area from archive', ... |
---|
36 | 'Callback', protect(@zoom_in_callback)); |
---|
37 | control('pushbutton', 'Spectrogram', 100, 'Show as spectrogram', ... |
---|
38 | 'Callback', protect(@spectrogram_callback)); |
---|
39 | h.message = control('text', '', 150, ... |
---|
40 | 'Error message or [bpm count] samples/decimation'); |
---|
41 | h.maxpts = control('edit', num2str(1e6), 80, ... |
---|
42 | 'Maximum number of sample points'); |
---|
43 | h.ylim = control('checkbox', 'Zoomed', 70, ... |
---|
44 | 'Limit vertical scale to +-100um', 'Value', 0, ... |
---|
45 | 'Callback', protect(@reload_plot)); |
---|
46 | h.data_type = control('popup', {'min/max', 'std', 'mean'}, 90, ... |
---|
47 | 'Choose decimated data type to display', 'Value', 1, ... |
---|
48 | 'Callback', protect(@reload_plot)); |
---|
49 | control('pushbutton', 'Save', 40, 'Save Position data currently displayed', ... |
---|
50 | 'Callback', protect(@save_data_callback)); |
---|
51 | clear global h_pos; |
---|
52 | h.history = cell(0, 2); |
---|
53 | |
---|
54 | % Hang onto the controls we need to reference later |
---|
55 | guidata(fig, h); |
---|
56 | |
---|
57 | last_day_callback(fig, 0); |
---|
58 | end |
---|
59 | |
---|
60 | |
---|
61 | % Places control with specified style, value, width and tooltip. |
---|
62 | function result = control(style, value, width, tooltip, varargin) |
---|
63 | global h_pos; |
---|
64 | position = [h_pos 10 width 20]; |
---|
65 | h_pos = h_pos + width + 5; |
---|
66 | result = uicontrol( ... |
---|
67 | 'Style', style, 'String', value, 'Position', position, ... |
---|
68 | 'TooltipString', tooltip, varargin{:}); |
---|
69 | end |
---|
70 | |
---|
71 | |
---|
72 | function prot = protect(func) |
---|
73 | function protected(fig, event) |
---|
74 | try |
---|
75 | func(fig, event) |
---|
76 | catch |
---|
77 | message('Error: see console') |
---|
78 | rethrow(lasterror) |
---|
79 | end |
---|
80 | end |
---|
81 | prot = @protected; |
---|
82 | end |
---|
83 | |
---|
84 | |
---|
85 | function back_callback(fig, event) |
---|
86 | h = guidata(fig); |
---|
87 | if size(h.history, 1) > 1 |
---|
88 | h.history = h.history(1:end-1, :); |
---|
89 | range = h.history{end, 1}; |
---|
90 | type = h.history{end, 2}; |
---|
91 | guidata(fig, h) |
---|
92 | load_data(fig, range, type, false); |
---|
93 | end |
---|
94 | end |
---|
95 | |
---|
96 | |
---|
97 | function full_archive_callback(fig, event) |
---|
98 | load_data(fig, [now-2000 now], 'D', true); % Go back as far as possible! |
---|
99 | end |
---|
100 | |
---|
101 | |
---|
102 | % Loads data for the last 24 hours |
---|
103 | function last_day_callback(fig, event) |
---|
104 | load_data(fig, [now-1 now], 'D', true); |
---|
105 | end |
---|
106 | |
---|
107 | |
---|
108 | % Loads data enclosed by the current zoom selection, returned by xlim. |
---|
109 | function zoom_in_callback(fig, event) |
---|
110 | h = guidata(fig); |
---|
111 | global data; |
---|
112 | |
---|
113 | maxdata = str2num(get(h.maxpts, 'String')); |
---|
114 | pvs = str2num(get(h.bpm_list, 'String')); |
---|
115 | points = diff(xlim) * 24 * 3600 * 10079 * length(pvs); |
---|
116 | |
---|
117 | type = 'F'; |
---|
118 | if points > maxdata |
---|
119 | type = 'd'; |
---|
120 | points = points / 64; |
---|
121 | if points > maxdata |
---|
122 | type = 'D'; |
---|
123 | end |
---|
124 | end |
---|
125 | |
---|
126 | load_data(fig, xlim + data.day, type, true); |
---|
127 | end |
---|
128 | |
---|
129 | |
---|
130 | function reload_plot(fig, event) |
---|
131 | h = guidata(fig); |
---|
132 | global data; |
---|
133 | plotfa(h, data); |
---|
134 | end |
---|
135 | |
---|
136 | |
---|
137 | % Loads the requested range of data. |
---|
138 | function load_data(fig, range, type, save) |
---|
139 | h = guidata(fig); |
---|
140 | if save |
---|
141 | h.history(end+1, :) = {range, type}; |
---|
142 | guidata(fig, h) |
---|
143 | end |
---|
144 | global data; |
---|
145 | |
---|
146 | pvs = str2num(get(h.bpm_list, 'String')); |
---|
147 | |
---|
148 | busy; |
---|
149 | data = fa_load(range, pvs, type, h.server); |
---|
150 | plotfa(h, data); |
---|
151 | describe; |
---|
152 | end |
---|
153 | |
---|
154 | |
---|
155 | function spectrogram_callback(fig, event) |
---|
156 | global data; |
---|
157 | %len=1024; |
---|
158 | len=20480; |
---|
159 | |
---|
160 | if length(size(data.data)) == 3 |
---|
161 | busy; |
---|
162 | for n = 1:2 |
---|
163 | subplot(2, 1, n) |
---|
164 | e = squeeze(data.data(n, 1, :)); |
---|
165 | cols = floor(length(e)/len); |
---|
166 | sg = log10(abs(fft(reshape(e(1:(len*cols)), len, cols)))); |
---|
167 | imagesc(data.t, [0 data.f_s/10], sg(1:(round(len/10)), :)); |
---|
168 | |
---|
169 | set(gca, 'Ydir', 'normal'); |
---|
170 | %caxis([2 6]) |
---|
171 | caxis('auto'); |
---|
172 | label_axis(n) |
---|
173 | end |
---|
174 | describe; |
---|
175 | else |
---|
176 | message('Decimated data'); |
---|
177 | end |
---|
178 | end |
---|
179 | |
---|
180 | function save_data_callback(fig, event) |
---|
181 | h = guidata(fig); |
---|
182 | global data; |
---|
183 | if length(size(data.data)) == 4 |
---|
184 | % decimated data can not be saved |
---|
185 | else |
---|
186 | BPM_list=family2tangodev('BPMx',data.ids') |
---|
187 | bufferX=squeeze(data.data(1, :, :)); |
---|
188 | bufferZ=squeeze(data.data(2, :, :)); |
---|
189 | if size(BPM_list,1)==1 |
---|
190 | bufferX=bufferX'; |
---|
191 | bufferZ=bufferZ'; |
---|
192 | end |
---|
193 | |
---|
194 | date=datestr(data.timestamp,30) |
---|
195 | date=[date(1:4),'_',date(5:6),'_',date(7:8),'_',date(10:11),'h_',date(12:13),'mn'] |
---|
196 | filename=['/home/operateur/GrpDiagnostics/matlab/data/Enregistrement_',date,'.mat']; |
---|
197 | |
---|
198 | uisave({'BPM_list','bufferX','bufferZ'},filename) |
---|
199 | end |
---|
200 | |
---|
201 | |
---|
202 | end |
---|
203 | |
---|
204 | function plotfa(h, d) |
---|
205 | data_type = get(h.data_type, 'Value'); |
---|
206 | if get(h.ylim, 'Value') |
---|
207 | if length(size(d.data)) == 4 |
---|
208 | switch data_type |
---|
209 | case 1; set_ylim = [-100 100]; |
---|
210 | case 2; set_ylim = [0 10]; |
---|
211 | case 3; set_ylim = [-10 10]; |
---|
212 | end |
---|
213 | else |
---|
214 | set_ylim = [-100 100]; |
---|
215 | end |
---|
216 | else |
---|
217 | set_ylim = []; |
---|
218 | end |
---|
219 | |
---|
220 | for n = 1:2 |
---|
221 | subplot(2, 1, n) |
---|
222 | if length(size(d.data)) == 4 |
---|
223 | switch data_type |
---|
224 | case 1 |
---|
225 | plot(d.t, 1e-3 * squeeze(d.data(n, 2, :, :))); hold on |
---|
226 | plot(d.t, 1e-3 * squeeze(d.data(n, 3, :, :))); hold off |
---|
227 | case 2 |
---|
228 | plot(d.t, 1e-3 * squeeze(d.data(n, 4, :, :))); |
---|
229 | case 3 |
---|
230 | plot(d.t, 1e-3 * squeeze(d.data(n, 1, :, :))); |
---|
231 | end |
---|
232 | else |
---|
233 | plot(d.t, 1e-3 * squeeze(d.data(n, :, :))) |
---|
234 | end |
---|
235 | |
---|
236 | xlim([d.t(1) d.t(end)]); |
---|
237 | if length(set_ylim) > 0; ylim(set_ylim); end |
---|
238 | label_axis(n) |
---|
239 | end |
---|
240 | end |
---|
241 | |
---|
242 | |
---|
243 | function label_axis(n) |
---|
244 | axes = {'X'; 'Y'}; |
---|
245 | global data; |
---|
246 | ylabel(gca, 'µm'); |
---|
247 | if diff(data.t([1 end])) <= 2/(24*3600) |
---|
248 | title([datestr(data.timestamp) ' ' axes{n}]) |
---|
249 | set(gca, 'XTickLabel', num2str( ... |
---|
250 | get(gca,'XTick').'*24*3600-60*floor(data.t(1)*24*60),'%.4f')) |
---|
251 | else |
---|
252 | title([datestr(data.day) ' ' axes{n}]) |
---|
253 | datetick('keeplimits') |
---|
254 | end |
---|
255 | end |
---|
256 | |
---|
257 | function message(msg) |
---|
258 | h = guidata(gcf); |
---|
259 | set(h.message, 'String', msg); |
---|
260 | end |
---|
261 | |
---|
262 | function busy |
---|
263 | message('Busy'); |
---|
264 | drawnow; |
---|
265 | end |
---|
266 | |
---|
267 | % Prints description of currently plotted data |
---|
268 | function describe |
---|
269 | global data; |
---|
270 | message(sprintf('[%d] %d/%d', ... |
---|
271 | length(data.ids), length(data.data), data.decimation)) |
---|
272 | end |
---|
273 | |
---|
274 | % Gives id from selected BPM Name |
---|
275 | function bpm_name_callback(fig, event) |
---|
276 | h = guidata(gcf); |
---|
277 | index = get(h.bpm_name_list, 'Value'); |
---|
278 | set(h.bpm_list, 'String', num2str(index)); |
---|
279 | end |
---|