source: MML/trunk/machine/SOLEIL/StorageRing/bpm/monbpm.m @ 17

Last change on this file since 17 was 17, checked in by zhangj, 10 years ago

To have a stable version on the server.

  • Property svn:executable set to *
File size: 11.8 KB
Line 
1function varargout = monbpm(varargin)
2%MONBPM - Monitors the orbit
3%  [BPMx, BPMy, tout, DCCT, BPMxSTD, BPMySTD, FileName] = monbpm(t, BPMxFamily, BPMxList, BPMyFamily, BPMyList, FileName)
4%  [BPMx, BPMy, FileName] = monbpm(... , 'Struct')
5%
6%  INPUTS
7%  1. t = time vector [seconds], or
8%         length of time in seconds to measure data (scalar)
9%         {Default: 3 minute at a sample rate of 2 Hz}
10%         {If empty, [], prompt for an input}
11%  2 and 4. BPMxFamily and BPMyFamily are the family names of the BPM's, {Default or []: the entire list}
12%  3 and 5. BPMxList and BPMyList are the device list of BPM's, {Default or []: the entire list}
13%  6. 'Struct'  will return data structures instead of vectors
14%     'Numeric' will return vector outputs {Default}
15%  7.  FileName = Filename (including directory) where the data was saved (if applicable)
16%  8. 'Archive'   - save a data array structure to \<BPMData Directory>\<BPMData><Date><Time>.mat  {Default}
17%     'NoArchive' - no data will be saved to file
18%     'Summary' - Sort BPM by decreasind STD value
19%
20%  OUTPUTS
21%  For numeric output:
22%  1-2. BPMx and BPMy are the raw orbit data matrices or structures
23%  3. DCCT is a row vector containing the beam current
24%  4. tout is a row vector of times as returned by getam           
25%  5-6. BPMxSTD and BPMySTD are standard deviation of the difference orbits
26%  7. FileName = Filename (including directory) where the data was saved (if applicable)
27%
28%  For structures:
29%  BPMxSTD and BPMySTD are the .Sigma field
30%
31%  NOTE
32%  1. All inputs are optional.  All of the following have the same output: 
33%     [BPMx, BPMz, t] = monbpm(0:.5:180);
34%     [BPMx, BPMz, t] = monbpm(0:.5:180, 'BPMx');
35%     [BPMx, BPMz, t] = monbpm('BPMx');
36%     [BPMx, BPMz, t] = monbpm('BPMx', 'BPMz');
37%     [BPMx, BPMz, t] = monbpm('BPMx', [], 'BPMz');
38%
39%  see Also plotmonbpm
40
41%
42%  Written by Gregory J. Portmann
43%  Adapted by Laurent S. Nadolski
44%  July 1st, 2007 Added New Flag SummaryFlag to sort BPM by STD by descreasing values
45
46% Defaults
47BPMxFamily = 'BPMx'; %gethbpmfamily; too slow
48BPMyFamily = 'BPMz'; %getvbpmfamily; too slow
49BPMxList = [];   
50BPMyList = [];   
51T = 3*60;
52Tsample = .5; % Sampling period
53t = [];
54DisplayFlag = 1;
55FileName = -1;
56ArchiveFlag = 0;
57StructOutputFlag = 0;
58Navg = getbpmaverages;
59SummaryFlag = 1;
60
61% for refreshing BPM data TANGO issue
62getx; getz;
63
64% Look if 'struct' or 'numeric' in on the input line
65for i = length(varargin):-1:1
66    if strcmpi(varargin{i},'Struct')
67        StructOutputFlag = 1;
68        varargin(i) = [];
69    elseif strcmpi(varargin{i},'Numeric')
70        StructOutputFlag = 0;
71        varargin(i) = [];
72    elseif strcmpi(varargin{i},'Archive')
73        ArchiveFlag = 1;
74        if length(varargin) > i
75            % Look for a filename as the next input
76            if ischar(varargin{i+1})
77                FileName = varargin{i+1};
78                varargin(i+1) = [];
79            end
80        end
81        varargin(i) = [];
82    elseif strcmpi(varargin{i},'NoArchive')
83        ArchiveFlag = 0;
84        varargin(i) = [];
85    elseif strcmpi(varargin{i},'NoDisplay')
86        DisplayFlag = 0;
87        varargin(i) = [];
88    elseif strcmpi(varargin{i},'Summary')
89        SummaryFlag = 1;
90        varargin(i) = [];
91    elseif strcmpi(varargin{i},'NoSummary')
92        SummaryFlag = 0;
93        varargin(i) = [];
94    elseif strcmpi(varargin{i},'Display')
95        DisplayFlag = 1;
96        varargin(i) = [];
97    end
98end
99
100
101% t input
102if length(varargin) >= 1
103    if isnumeric(varargin{1})
104        t = varargin{1};
105        varargin(1) = [];
106
107        if isempty(t)
108            prompt = {'Input the sample period (seconds)', 'Input the total data collection time (seconds)'};
109            answer = inputdlg(prompt,'monbpm',1,{'.5','180'});
110            if isempty(answer)
111                fprintf('   monbpm canceled\n');
112                return
113            end
114            T       = str2num(answer{1});
115            EndTime = str2num(answer{2});
116            t = 0:T:EndTime;
117        end
118    end
119end
120
121% Look for BPMx family info
122if length(varargin) >= 1
123    if ischar(varargin{1})
124        BPMxFamily = varargin{1};
125        varargin(1) = [];
126        if length(varargin) >= 1
127            if isnumeric(varargin{1})
128                BPMxList = varargin{1};
129                varargin(1) = [];
130            end
131        end
132    else
133        if isnumeric(varargin{1})
134            BPMxList = varargin{1};
135            varargin(1) = [];
136        end
137    end
138end
139
140% Look for BPMy family info
141if length(varargin) >= 1
142    if ischar(varargin{1})
143        BPMyFamily = varargin{1};
144        varargin(1) = [];
145        if length(varargin) >= 1
146            if isnumeric(varargin{1})
147                BPMyList = varargin{1};
148                varargin(1) = [];
149            end
150        end
151    else
152        if isnumeric(varargin{1})
153            BPMyList = varargin{1};
154            varargin(1) = [];
155        end
156    end
157end
158
159% Look for FileName info
160if length(varargin) >= 1
161    if ischar(varargin{1})
162        FileName = varargin{1};
163    end
164end
165
166if isempty(t)
167    t = 0:Tsample:T;
168end
169
170% Make a row vector
171t = t(:)';
172
173% If scalar, create a vector
174if length(t) == 1
175    t = 0:Tsample:t;
176end
177
178
179if ArchiveFlag
180    if isempty(FileName)
181        FileName = appendtimestamp('BPMData');
182        DirectoryName = getfamilydata('Directory','BPMData');
183        if isempty(DirectoryName)
184            DirectoryName = [getfamilydata('Directory','DataRoot'), filesep, 'BPM', filesep];
185        else
186            % Make sure default directory exists
187            DirStart = pwd;
188            [DirectoryName, ErrorFlag] = gotodirectory(DirectoryName);
189            cd(DirStart);
190        end
191        [FileName, DirectoryName] = uiputfile('*.mat', 'Select a BPM Monitor File', [DirectoryName FileName]);
192        if FileName == 0
193            ArchiveFlag = 0;
194            fprintf('   monbpm canceled\n');
195            varargout{1} = [];
196            return
197        end
198        FileName = [DirectoryName, FileName];
199    elseif FileName == -1
200        FileName = appendtimestamp('BPMData');
201        DirectoryName = getfamilydata('Directory','BPMData');
202        if isempty(DirectoryName)
203            DirectoryName = [getfamilydata('Directory','DataRoot'), filesep, 'BPM', filesep];
204        end
205        FileName = [DirectoryName, FileName];
206    end
207end
208
209
210if DisplayFlag
211    fprintf('   Monitoring orbit and current for %.1f seconds\n', t(end)); drawnow;
212end
213TimeStart = gettime;
214
215if isfamily('DCCT')
216    AM = getam({BPMxFamily, BPMyFamily, 'DCCT'}, {BPMxList, BPMyList,[]}, t, 'struct');
217    DCCT = AM{3};
218else
219    AM = getam({BPMxFamily, BPMyFamily}, {BPMxList, BPMyList}, t, 'struct');
220    DCCT = [];
221end
222BPM(1) = AM{1};
223BPM(2) = AM{2};
224
225BPM(1).NumberOfAverages = Navg;
226BPM(1).DCCT = DCCT;
227BPM(1).CreatedBy = 'monbpm';
228BPM(1).DataDescriptor = 'Orbit Data';
229
230BPM(2).NumberOfAverages = Navg;
231BPM(2).DCCT = DCCT;
232BPM(2).CreatedBy = 'monbpm';
233BPM(2).DataDescriptor = 'Orbit Data';
234
235
236
237if DisplayFlag
238    tout = BPM(1).tout;
239    Mx = BPM(1).Data;
240    % Orbit compared to first set
241    for i = 1:size(Mx,2)
242        Mx(:,i) = Mx(:,i) - BPM(1).Data(:,1);
243    end
244
245    figure
246    subplot(2,2,1);
247    plot(tout, Mx);
248    grid on;
249    %title(sprintf('BPM Data (%s)', datestr(BPM(1).TimeStamp)))
250    xlabel('Time [Seconds]');
251    ylabel('Horizontal Relative Position [mm]');
252    axis tight
253   
254    tout = BPM(2).tout;
255    % Orbit compared to first set
256    My = BPM(2).Data;
257    for i = 1:size(My,2)
258        My(:,i) = My(:,i) -  BPM(2).Data(:,1);
259    end
260   
261    subplot(2,2,3);
262    plot(tout, My);
263    grid on;
264    xlabel('Time [Seconds]');
265    ylabel(sprintf('Vertical Position [%s]', BPM(2).UnitsString));
266    axis tight
267end
268
269
270% Warn if the measurement did not keep in time step with t
271tmeas = tout-t;
272if any(tmeas(1:end-1) > 1.05*diff(t))
273    fprintf('   WARNING: The time allotted for getting data is too small\n');
274end
275
276
277
278% Compute the standard deviation
279if 0
280    % Definition of standard deviations
281    BPM(1).Sigma = std(BPM(1).Data,0,2);
282    BPM(2).Sigma = std(BPM(2).Data,0,2);
283   
284else
285   
286    % Low frequency drifting increases the STD.  For many purposes, like LOCO,
287    % this is not desireable.  Using difference orbits mitigates the drift problem.
288    Mx = BPM(1).Data;
289    for i = 1:size(Mx,2)-1
290        Mx(:,i) = Mx(:,i+1) - Mx(:,i);
291    end
292    Mx(:,end) = [];
293   
294    My = BPM(2).Data;
295    for i = 1:size(My,2)-1
296        My(:,i) = My(:,i+1) - My(:,i);
297    end
298    My(:,end) = [];
299   
300    BPM(1).Sigma = std(Mx,0,2) / sqrt(2);   % sqrt(2) comes from substracting 2 random variables
301    BPM(2).Sigma = std(My,0,2) / sqrt(2);
302   
303end
304
305if DisplayFlag
306    subplot(2,2,2);
307    List = BPM(1).DeviceList;
308    Nsectors = max(List(:,1));
309    Ndevices = max(List(:,2));
310    Sector = List(:,1) + List(:,2)/Ndevices + 1/Ndevices/2;
311    [Sector Idx] = sort(Sector);
312    plot(Sector, BPM(1).Sigma(Idx));
313    grid on;
314    xaxis([1 Nsectors+1])
315    set(gca,'XTick',1:Nsectors);
316    xlabel('Sector Number');
317    ylabel(sprintf('Horizontal STD [%s]', BPM(1).UnitsString));
318   
319    subplot(2,2,4);
320    List = BPM(2).DeviceList;
321    Nsectors = max(List(:,1));
322    Ndevices = max(List(:,2));
323    Sector = List(:,1) + List(:,2)/Ndevices + 1/Ndevices/2;
324    [Sector Idx] = sort(Sector);   
325    plot(Sector, BPM(2).Sigma(Idx));
326    grid on;
327    xaxis([1 Nsectors+1])
328    set(gca,'XTick',1:Nsectors);
329    xlabel('Sector Number');
330    ylabel(sprintf('Vertical STD [%s]', BPM(2).UnitsString));
331 
332    addlabel(.5,1,sprintf('BPM Data (%s)', datestr(BPM(1).TimeStamp)), 10);
333    orient landscape
334end
335
336
337% Save data in the proper directory
338if ArchiveFlag | ischar(FileName)
339    [DirectoryName, FileName, Ext] = fileparts(FileName);
340    DirStart = pwd;
341    [DirectoryName, ErrorFlag] = gotodirectory(DirectoryName);
342    if ErrorFlag
343        fprintf('\n   There was a problem getting to the proper directory!\n\n');
344    end
345    BPMxData = BPM(1);
346    BPMyData = BPM(2);
347    save(FileName, 'BPMxData', 'BPMyData');
348    %save(FileName, 'BPM');
349    cd(DirStart);
350    FileName = [DirectoryName, FileName, '.mat'];
351
352    if DisplayFlag
353        fprintf('   BPM data saved to %s\n', FileName);
354        fprintf('   The total measurement time was %.2f minutes.\n', (gettime-TimeStart)/60);
355    end
356else
357    FileName = '';
358end
359
360
361if SummaryFlag
362    [SortedData1 DataIdx1] = sort(BPM(1).Sigma,'descend');
363    SortedDeviceList1 = BPM(1).DeviceList(DataIdx1,:);
364    [SortedData2 DataIdx2] = sort(BPM(2).Sigma,'descend');
365    SortedDeviceList2 = BPM(2).DeviceList(DataIdx2,:);
366
367    % sort by drift
368    maxBPM1 =  max(abs(Mx),[],2);
369    [SortedData3 DataIdx3] = sort(maxBPM1,'descend');
370    SortedDeviceList3 = BPM(1).DeviceList(DataIdx3,:);
371    maxBPM2 =  max(abs(My),[],2);
372    [SortedData4 DataIdx4] = sort(maxBPM2,'descend');
373    SortedDeviceList4 = BPM(2).DeviceList(DataIdx4,:);
374   
375    fprintf('\n\n BPMxname DevList     Max drift           BPMzname DevList       Max drift\n');
376    for k=1:size(BPM(1).DeviceList,1),
377        fprintf('%s    [%2d %2d]      %6.2e [%s]        %s    [%2d %2d]      %6.2e [%s] \n', ...
378            'BPMx', SortedDeviceList3(k,1), SortedDeviceList3(k,2), SortedData3(k), BPM(1).UnitsString, ...
379            'BPMz', SortedDeviceList4(k,1), SortedDeviceList4(k,2), SortedData4(k), BPM(2).UnitsString);
380    end
381
382    fprintf('\n\n BPMxname DevList     STD value           BPMzname DevList       STD value\n');
383    for k=1:size(BPM(1).DeviceList,1),
384        fprintf('%s    [%2d %2d]      %6.2e [%s]        %s    [%2d %2d]      %6.2e [%s] \n', ...
385            'BPMx', SortedDeviceList1(k,1), SortedDeviceList1(k,2), SortedData1(k), BPM(1).UnitsString, ...
386            'BPMz', SortedDeviceList2(k,1), SortedDeviceList2(k,2), SortedData2(k), BPM(2).UnitsString);
387    end
388end
389
390if StructOutputFlag
391    % Output variables
392    varargout{1} = BPM(1);   
393    varargout{2} = BPM(2);   
394    varargout{3} = FileName;
395else
396    % Output variables
397    varargout{1} = BPM(1).Data;
398    varargout{2} = BPM(2).Data;
399    varargout{3} = tout;
400    varargout{4} = DCCT;
401    varargout{5} = BPM(1).Sigma;
402    varargout{6} = BPM(2).Sigma;
403    varargout{7} = FileName;
404end
Note: See TracBrowser for help on using the repository browser.