source: MML/trunk/mml/measdisp.m @ 4

Last change on this file since 4 was 4, checked in by zhangj, 11 years ago

Initial import--MML version from SOLEIL@2013

File size: 17.6 KB
Line 
1function [Dx, Dy, FileName] = measdisp(varargin)
2%MEASDISP - Measures the dispersion function
3%  [Dx, Dy, FileName] = measdisp(DeltaRF, BPMxFamily, BPMxList, BPMyFamily, BPMyList, WaitFlag, ModulationMethod)
4%
5%  Examples:
6%  [Dx, Dy] = measdisp(DeltaRF, BPMxList, BPMyList)
7%  [Dx, Dy] = measdisp('BPMx', [], 'BPMz')
8%  [Dx, Dy] = measdisp(DeltaRF, 'Physics', mcf)
9%  [Dx, Dy] = measdisp(DeltaRF, 'Physics')
10%  [Dx, Dy] = measdisp
11%  [Dx, Dy] = measdisp('Archive')
12%  [Dx, Dy] = measdisp('Struct')
13%
14%  INPUTS
15%  1. DeltaRF is the change in RF frequency {Default: .2% energy change}
16%     Units match the units the RF family is in (or the override units)
17%  2. BPMxFamily and BPMyFamily are the family names of the BPM's, {Default: gethbpmfamily, getvbpmfamily}
18%  3. BPMxList and BPMyList are the device list of BPM's, {Default or []: the entire list}
19%  4. WaitFlag >= 0, wait WaitFlag seconds before measuring the tune (sec)
20%               = -1, wait until the magnets are done ramping
21%               = -2, wait until the magnets are done ramping + BPM processing delay {Default}
22%               = -4, wait until keyboard input
23%  5. Modulation method for changing the RF frequency
24%     'bipolar'  changes the RF by +/- DeltaRF/2 {Default}
25%     'unipolar' changes the RF from 0 to DeltaRF
26%  6. 'Physics' - For actual dispersion units (m/(dp/p)) add 'Physics' with an optional input
27%     of the momentum compaction factor.  If empty, the mcf will be found from the getmcf
28%     function.  That mean the model must be correct for the dispersion to be scaled properly.  For
29%     instance, when measuring the disperison of the injection lattice the model lattice
30%     would have to reflect the injection lattice too.  If not, override mcf on the input line.
31%     'Hardware' in the input line forces hardware units, usually mm/MHz.  The actual units will
32%     depend on the units for the BPM and RF families.
33%  7. 'Struct'  will return data structures instead of vectors {Default for data structure inputs}
34%     'Numeric' will return vector outputs {Default for non-data structure inputs}
35%  8. Optional override of the mode
36%     'Online'    - Set/Get data online 
37%     'Simulator' - Set/Get data on the simulated accelerator using AT (ie, same commands as 'Online')
38%     'Model'     - (same as Simulator, use modeldisp to get the model dispersion with no BPM errors)
39%     'Manual'    - Set/Get data manually
40%  9. Optional display
41%     'Display'   - Plot the dispersion {Default if no outputs exist}
42%     'NoDisplay' - Dispersion will not be plotted {Default if outputs exist}
43%  10.'NoArchive' - No file archive {Default}
44%     'Archive'   - Save a dispersion data structure to \<Directory.DispData>\<DispArchiveFile><Date><Time>.mat
45%                   To change the filename, included the filename after the 'Archive', '' to browse
46%
47%  OUTPUTS
48%  For hardware units:
49%  Dx = Delta BPMx / Delta RF and Dy = Delta BPMy / Delta RF
50%       hence Dx and Dy are not quite the definition of dispersion
51%
52%               x2(RF0+DeltaRF/2) - x1(RF0-DeltaRF/2)
53%           D = -------------------------------------
54%                              DeltaRF
55%           
56%           where RF0 = is the present RF frequency
57%
58%  For physics units:
59%  DeltaRF is converted to change in energy, dp/p
60%
61%  The units for orbit change depend on what the hardware or physics units are. 
62%  Typical units are mm for hardware and meters for physics.
63%
64%  Structure outputs have the following fields:
65%                  Data: [double] - orbit shift with RF or energy shift
66%            FamilyName: 'DispersionX' or 'DispersionY'
67%              Actuator: [1x1 struct] - RF structure with starting frequency
68%         ActuatorDelta: Change in RF in hardware units
69%               Monitor: [1x1 struct] - BPM structure with starting orbit
70%                   GeV: Storage ring energy
71%             TimeStamp: Clock (for example, [2003 7 9 0 21 36.2620])
72%                  DCCT: Beam current
73%      ModulationMethod: 'bipolar' or 'unipolar'
74%              WaitFlag: BPM wait flag (usually -2)
75%            ExtraDelay: 0
76%        DataDescriptor: 'Dispersion'
77%             CreatedBy: 'measdisp'
78%                   MCF: momentum compaction factor
79%                 Units: 'Hardware' or 'Physics'
80%           UnitsString: typically 'mm/MHz' or meters/(dp/p)
81%                    dp: change in moment
82%                 Orbit: [2 column vectors]  (orbit at RF0+DeltaRF/2 and RF0-DeltaRF/2)
83%                    RF: [RF0+DeltaRF/2 RF0-DeltaRF/2]
84%
85%  If no output exists, the dispersion function will be plotted to the screen.
86%
87%  NOTES
88%  1. 'Hardware', 'Physics', 'Eta', 'Archive', 'Numeric', and 'Struct' are not case sensitive
89%  2. 'Eta' can be used instead of 'Physics'
90%  3.  Get and set the RF frequency are done with getrf and setrf
91%  4.  RF frequency is changed by +/-(DeltaRF/2)
92%  5.  All inputs are optional
93%  6.  Units for DeltaRF depend on the 'Physics' or 'Hardware' flags
94%
95%  See also plotdisp, modeldisp, measchro
96
97%
98%  Written by Gregory J. Portmann and Jeff Corbett
99%  Modified by Laurent S. Nadolski
100%  March 2009, add coupling flag
101
102% DeltaRFphysics max currently 15 kHz.
103
104BPMxFamily = gethbpmfamily;
105BPMyFamily = getvbpmfamily;
106BPMxList = [];
107BPMyList = [];
108CouplingFlag = 1;
109
110WaitFlag = -2;
111if iscontrolroom
112    ExtraDelay = 5; % seconds;
113else
114    ExtraDelay = 0;
115end
116ModulationMethod = 'bipolar';
117StructOutputFlag = 0;
118NumericOutputFlag = 0;
119ArchiveFlag = 0;
120FileName = -1;
121if nargout == 0
122    DisplayFlag = 1;
123else
124    DisplayFlag = 0;
125end
126ModeFlag = {};  % model, online, manual, or '' for default mode
127UnitsFlag = ''; % hardware, physics, or '' for default units
128MCF = [];
129
130
131InputFlags = {};
132for i = length(varargin):-1:1
133    if isstruct(varargin{i})
134        % Ignore structures
135    elseif iscell(varargin{i})
136        % Ignore cells
137    elseif strcmpi(varargin{i},'struct')
138        StructOutputFlag = 1;
139        varargin(i) = [];
140    elseif strcmpi(varargin{i},'numeric')
141        NumericOutputFlag = 1;
142        StructOutputFlag = 0;
143        varargin(i) = [];
144    elseif strcmpi(varargin{i},'archive')
145        ArchiveFlag = 1;
146        if length(varargin) > i
147            % Look for a filename as the next input
148            if ischar(varargin{i+1})
149                FileName = varargin{i+1};
150                varargin(i+1) = [];
151            end
152        end
153        varargin(i) = [];
154    elseif strcmpi(varargin{i},'noarchive')
155        ArchiveFlag = 0;
156        varargin(i) = [];
157    elseif strcmpi(varargin{i},'Display')
158        DisplayFlag = 1;
159        varargin(i) = [];
160    elseif strcmpi(varargin{i},'NoDisplay')
161        DisplayFlag = 0;
162        varargin(i) = [];
163    elseif strcmpi(varargin{i},'bipolar')
164        ModulationMethod = 'bipolar';
165        varargin(i) = [];
166    elseif strcmpi(varargin{i},'unipolar')
167        ModulationMethod = 'unipolar';
168        varargin(i) = [];
169    elseif strcmpi(varargin{i},'eta') || strcmpi(varargin{i},'physics')
170        UnitsFlag = 'Physics';
171        varargin(i) = [];
172        if length(varargin) >= i
173            if isnumeric(varargin{i})
174                MCF = varargin{i};
175                varargin(i) = [];
176            end
177        end
178    elseif strcmpi(varargin{i},'hardware')
179        UnitsFlag = varargin{i};
180        varargin(i) = [];
181        if length(varargin) >= i
182            if isnumeric(varargin{i})
183                MCF = varargin{i};
184                varargin(i) = [];
185            end
186        end
187    elseif strcmpi(varargin{i},'simulator') || strcmpi(varargin{i},'model')
188        ModeFlag = varargin(i);
189        varargin(i) = [];
190    elseif strcmpi(varargin{i},'online')
191        ModeFlag = varargin(i);
192        varargin(i) = [];
193    elseif strcmpi(varargin{i},'manual')
194        ModeFlag = varargin(i);
195        varargin(i) = [];
196    end       
197end
198
199
200% Look for DeltaRF input
201if length(varargin) >= 1
202    if isnumeric(varargin{1})
203        DeltaRF = varargin{1};
204        varargin(1) = [];
205    else
206        DeltaRF = [];
207    end
208else
209    DeltaRF = [];
210end
211
212% Look for BPMx family info
213if length(varargin) >= 1
214    if ischar(varargin{1})
215        BPMxFamily = varargin{1};
216        varargin(1) = [];
217        if length(varargin) >= 1
218            if isnumeric(varargin{1})
219                BPMxList = varargin{1};
220                varargin(1) = [];
221            end
222        end
223    elseif isnumeric(varargin{1})
224        BPMxList = varargin{1};
225        varargin(1) = [];
226    elseif isstruct(varargin{1})
227        BPMxFamily = varargin{1}.FamilyName;
228        BPMxList = varargin{1}.DeviceList;
229        if isempty(UnitsFlag)
230            UnitsFlag = varargin{1}.Units;
231        end
232        if ~NumericOutputFlag
233            % Only change StructOutputFlag if 'numeric' is not on the input line
234            StructOutputFlag = 1;
235        end
236        varargin(1) = [];     
237    end
238end
239
240% Look for BPMy family info
241if length(varargin) >= 1
242    if ischar(varargin{1})
243        BPMyFamily = varargin{1};
244        varargin(1) = [];
245        if length(varargin) >= 1
246            if isnumeric(varargin{1})
247                BPMyList = varargin{1};
248                varargin(1) = [];
249            end
250        end
251    elseif isnumeric(varargin{1})
252        BPMyList = varargin{1};
253        varargin(1) = [];
254    elseif isstruct(varargin{1})
255        BPMyFamily = varargin{1}.FamilyName;
256        BPMyList = varargin{1}.DeviceList;
257        if isempty(UnitsFlag)
258            UnitsFlag = varargin{1}.Units;
259        end
260        if ~NumericOutputFlag
261            % Only change StructOutputFlag if 'numeric' is not on the input line
262            StructOutputFlag = 1;
263        end
264        varargin(1) = [];     
265    end
266end
267
268% Look for WaitFlag input
269if length(varargin) >= 1
270    if isnumeric(varargin{1}) && ~isempty(varargin{1})
271        WaitFlag = varargin{1};
272        varargin(1) = [];
273    end
274end
275% End of input parsing
276
277
278% Archive data structure
279if ArchiveFlag
280    if isempty(FileName)
281        FileName = appendtimestamp(getfamilydata('Default', 'DispArchiveFile'));
282        DirectoryName = getfamilydata('Directory','DispData');
283        if isempty(DirectoryName)
284            DirectoryName = [getfamilydata('Directory','DataRoot') 'Dispersion', filesep];
285        else
286            % Make sure default directory exists
287            DirStart = pwd;
288            [DirectoryName, ErrorFlag] = gotodirectory(DirectoryName);
289            cd(DirStart);
290        end
291        [FileName, DirectoryName] = uiputfile('*.mat', 'Select Dispersion File', [DirectoryName FileName]);
292        drawnow;
293        if FileName == 0
294            ArchiveFlag = 0;
295            disp('   Dispersion measurement canceled.');
296            Dx=[]; Dy=[]; FileName='';
297            return
298        end
299        FileName = [DirectoryName, FileName];
300    elseif FileName == -1
301        FileName = appendtimestamp(getfamilydata('Default', 'DispArchiveFile'));
302        DirectoryName = getfamilydata('Directory','DispData');
303        if isempty(DirectoryName)
304            DirectoryName = [getfamilydata('Directory','DataRoot') 'Dispersion', filesep];
305        end
306        FileName = [DirectoryName, FileName];
307    end
308end
309
310
311% Get the input units
312if isempty(UnitsFlag)
313    RFUnitsInput = getfamilydata('RF','Setpoint','Units');
314    UnitsFlag = RFUnitsInput;
315else
316    RFUnitsInput = UnitsFlag;
317end
318
319
320% Get DeltaRF in Hardware units
321RFHWUnits = getfamilydata('RF','Setpoint','HWUnits');
322
323
324% Make sure DeltaRF is in hardware units
325if isempty(DeltaRF) || ~isnumeric(DeltaRF)
326    % Get the default from the AD is in Hardware units
327    DeltaRF = getfamilydata('DeltaRFDisp');
328   
329    % If the default is not in the AD
330    if isempty(DeltaRF)
331        % Here is the second level default
332        DeltaRF = getrf('Hardware', ModeFlag{:}) * getmcf * .002;  % .2% energy change
333    end
334
335else
336    if strcmpi(UnitsFlag, 'Physics')
337        % Change to hardware
338        RFUnitsInput = UnitsFlag;
339        DeltaRF = physics2hw('RF', 'Setpoint', DeltaRF, []);
340    end
341end
342
343% DeltaRF must be in hardware units at this point
344
345
346% Use the AT model directly (measdisp or modeldisp)
347if ~isempty(ModeFlag) && strcmpi(ModeFlag{1}, 'Model')
348    % Measure in hardware and convert later
349    if 1
350        % Simulator mode (just so that the BPM gain or rotation errors are in the dispersion)
351        [HorDisp, VertDisp] = measdisp(DeltaRF, BPMxFamily, BPMxList, BPMyFamily, BPMyList, WaitFlag, ModulationMethod, 'Simulator', 'Struct', 'Hardware');
352       
353    else
354        % Use the AT Model (no BPM gain or rotation errors)
355        [HorDisp, VertDisp] = modeldisp(DeltaRF, BPMxFamily, BPMxList, BPMyFamily, BPMyList, ModulationMethod, 'Struct', 'Hardware');
356    end
357   
358    % This might not always work (it's only a problem if the first input family is in the vertical plane)
359    if ~isempty(strfind(lower(BPMxFamily),'z')) || ~isempty(strfind(lower(BPMxFamily),'v'))
360        d(1) = VertDisp;
361        d(2) = HorDisp;
362        d(1).Monitor = getam(BPMyFamily, BPMyList, 'Model', 'Struct', 'Hardware');
363        d(2).Monitor = getam(BPMxFamily, BPMxList, 'Model', 'Struct', 'Hardware');
364    else
365        d(1) = HorDisp;
366        d(2) = VertDisp;
367        d(1).Monitor = getam(BPMxFamily, BPMxList, 'Model', 'Struct', 'Hardware');
368        d(2).Monitor = getam(BPMyFamily, BPMyList, 'Model', 'Struct', 'Hardware');
369    end
370   
371    if isempty(MCF)
372        MCF = getmcf('Model');
373    end
374       
375    d(1).Actuator = getrf(d(1).Actuator.UnitsString, 'Model', 'Struct', 'Hardware');
376    d(2).Actuator = d(1).Actuator;
377   
378else
379    % Online & Simulation Modes
380       
381    % Check DeltaRF for resonable values
382    DeltaRFphysics = hw2physics('RF', 'Setpoint', DeltaRF, []);
383    if DeltaRFphysics > 15000;  % Hz
384        tmp = questdlg(sprintf('%f Hz is a large RF change.  Do you want to continue?', DeltaRFphysics),'Dispersion Measurement','YES','NO','YES');
385        if strcmp(tmp,'NO')
386            Dx=[];  Dy=[];
387            return
388        end
389    end
390
391    % Dispersion can be found using the response matrix generation program
392    if DisplayFlag
393        %DispRespMat = measrespmat({getam(BPMxFamily,BPMxList,'Struct','Hardware',ModeFlag), getam(BPMyFamily,BPMyList,'Struct',ModeFlag)}, getsp('RF','Struct',ModeFlag), DeltaRF, ModulationMethod, WaitFlag, ExtraDelay, 'Struct', 'Display', 'Hardware', ModeFlag{:});
394        DispRespMat = measrespmat({BPMxFamily,BPMyFamily}, {BPMxList,BPMyList}, 'RF', [], DeltaRF, ModulationMethod, WaitFlag, ExtraDelay, 'Struct', 'Display', 'Hardware', ModeFlag{:});
395    else
396        %DispRespMat = measrespmat({getam(BPMxFamily,BPMxList,'Struct','Hardware',ModeFlag), getam(BPMyFamily,BPMyList,'Struct',ModeFlag)}, getsp('RF','Struct',ModeFlag), DeltaRF, ModulationMethod, WaitFlag, ExtraDelay, 'Struct', 'NoDisplay', 'Hardware', ModeFlag{:});
397        DispRespMat = measrespmat({BPMxFamily,BPMyFamily}, {BPMxList,BPMyList}, 'RF', [], DeltaRF, ModulationMethod, WaitFlag, ExtraDelay, 'Struct', 'NoDisplay', 'Hardware', ModeFlag{:});
398    end
399   
400    d(1) = DispRespMat{1};
401    d(2) = DispRespMat{2};
402
403   
404    % For multiple RF cavities in the model it's possible to get multiple columns in the response matrix
405    if size(d(1).Data,2) > 1
406        % More Actuators means the RF was implemented as multiple cavities and not 1 RF frequency
407        % This is really not recommended!!!
408        d(1).Data = sum(d(1).Data,2);       
409        d(1).Actuator.Data       = d(1).Actuator.Data(1);
410        d(1).Actuator.DeviceList = d(1).Actuator.DeviceList(1);
411        d(1).Actuator.Status     = d(1).Actuator.Status(1);
412        d(1).Actuator.DataTime   = d(1).Actuator.DataTime(1);
413       
414        d(2).Data = sum(d(2).Data,2);
415        d(2).Actuator.Data       = d(2).Actuator.Data(1);
416        d(2).Actuator.DeviceList = d(2).Actuator.DeviceList(1);
417        d(2).Actuator.Status     = d(2).Actuator.Status(1);
418        d(2).Actuator.DataTime   = d(2).Actuator.DataTime(1);
419       
420        DeltaRFphysics = DeltaRFphysics(1);
421    end
422
423
424    % Get the momentum compaction factor in if was not on the input line
425    if isempty(MCF)
426        MCF = getmcf(ModeFlag);
427    end
428end
429
430
431d(1).FamilyName = 'DispersionX';
432d(2).FamilyName = 'DispersionY';
433d(1).GeV = getenergy(ModeFlag{:});
434d(2).GeV = d(1).GeV;
435
436
437for i = 1:2
438    d(i).MCF = MCF;
439    d(i).dp = -DeltaRF / (d(i).Actuator.Data * MCF);   
440    d(i).Mode = d(i).Actuator.Mode;
441    d(i).Units = d(i).Actuator.Units;
442    d(i).UnitsString = [d(i).Monitor.UnitsString,'/',d(i).Actuator.UnitsString];
443    d(i).OperationalMode = getfamilydata('OperationalMode');
444    d(i).DataDescriptor = 'Dispersion';
445    d(i).CreatedBy = 'measdisp';
446end
447
448
449% Final units conversion
450if strcmpi(RFUnitsInput, 'Physics')
451    d = hw2physics(d);
452end
453
454
455% Plot if no output
456if DisplayFlag
457    %figure;
458    if strcmpi(d(1).Mode,'Online') && CouplingFlag
459        % Take into account coupling and gain for the BPMs
460        Data = family2coupling(d(1).Monitor.DeviceList);
461        for ik =1:size(d(1).Monitor.DeviceList,1),
462            eta = Data.Cinv{ik}(:,:)*[d(1).Monitor.Data(ik); d(2).Monitor.Data(ik)];
463            d(1).Monitor.Data(ik) = eta(1);  d(2).Monitor.Data(ik) =  eta(2);
464        end
465    end
466    plotdisp(d(1),d(2));   
467end
468
469% Archive data structure
470if ArchiveFlag
471    % If the filename contains a directory then make sure it exists
472    [DirectoryName, FileName, Ext] = fileparts(FileName);
473    DirStart = pwd;
474    [DirectoryName, ErrorFlag] = gotodirectory(DirectoryName);
475    BPMxDisp = d(1);
476    BPMyDisp = d(2);
477    save(FileName, 'BPMxDisp', 'BPMyDisp');
478    if DisplayFlag
479        fprintf('   Dispersion data saved to %s.mat\n', [DirectoryName FileName]);
480        if ErrorFlag
481            fprintf('   Warning: %s was not the desired directory\n', DirectoryName);
482        end
483    end
484    cd(DirStart);
485    FileName = [DirectoryName, FileName, '.mat'];
486end
487if FileName == -1
488    FileName = '';
489end
490
491
492% Output
493if StructOutputFlag
494    Dx = d(1);
495    Dy = d(2);
496else
497    Dx = d(1).Data;
498    Dy = d(2).Data;
499end
500
501
502if DisplayFlag
503    fprintf('   Dispersion measurement complete\n');
504end
505
506
507
Note: See TracBrowser for help on using the repository browser.