source: MML/trunk/mml/meastuneresp.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: 19.3 KB
Line 
1function [Rmat, OutputFileName] = meastuneresp(varargin)
2%MEASTUNERESP - Measures the response from quadrupole to tune
3%  [R, FileName] = meastuneresp(ActuatorFamily, ActuatorDeviceList, ActuatorDelta, ModulationMethod, WaitFlag, FileName, DirectoryName, ExtraDelay)
4%
5%  INPUTS
6%  1. ActuatorFamily = Family name or cell array of family nams {Default: {'Q7','Q9'}}
7%  2. ActuatorDeviceList = Device list {Default: [], the entire family}
8%                          (Note: all devices in DeviceList are changed at the same time)
9%  3. ActuatorDelta = Change in magnet strength {Default: getfamilydata('ActuatorFamily','Setpoint','DeltaRespMat')}
10%  4. ModulationMethod - 'Unipolar' is the default since hysteresis is usually an issue (see help measrespmat)
11%  5. If WaitFlag >= 0, then WaitFlag is the delay before measuring the tune (sec)
12%                 = -3, then a delay of getfamilydata('TuneDelay') is used {Default}
13%                 = -4, then pause until keyboard input
14%                 = -5, then input the tune measurement manually by keyboard input
15%  6. Optional input to change the default filename and directory
16%     FileName - Filename for the response matrix data
17%                (No input or empty means data will be saved to the default file (except for model response matrices)) 
18%     DirectoryName - Directory name to store the response matrix data file
19%     Note: a. FileName can include the path if DirectoryName is not used
20%           b. For model response matrices, FileName must exist for a file save
21%           c. When using the default FileName, a dialog box will prompt for changes
22%
23%  7. ExtraDelay - extra time delay [seconds] after a setpoint change
24%
25%  8. 'Struct' will return a response matrix structure
26%     'Numeric' will return a matrix output {Default}
27%     'Matrix'  - Return a matrix output {Default}
28%         
29%                 Note: 'Matrix' is only a valid flag for Numeric outputs
30%                 Often use with the model input.  For example, to compare the model
31%                 tune response matrix to the default matrix,
32%                 Mmodel = meastuneresp('Model','Matrix');
33%                 Mmeas  = gettuneresp;
34%
35%  9. Optional override of the units:
36%     'Physics'  - Use physics  units
37%     'Hardware' - Use hardware units
38%
39%  10. Optional override of the mode:
40%      'Online'    - Set/Get data online 
41%      'Model'     - Get the model chromaticity directly from AT (uses modeltune)
42%      'Simulator' - Set/Get data on the simulated accelerator using AT (ie, same commands as 'Online')
43%      'Manual'    - Set/Get data manually
44%
45%  11. 'Display'    - Prints status information to the command window {Default}
46%      'NoDisplay'  - Nothing is printed to the command window
47%
48%  12. 'Archive' - Save the response matrix structure {Default, unless Mode='Model'}
49%      'NoArchive' - Save the response matrix structure
50%
51%  OUTPUTS
52%  R = Response matrix from delta quadrupole to delta tune
53%
54%      If more than one quadrupole family is input, the R is a cell array indexed by
55%      quadrupole family (ie, the number of families in ActuatorFamily).  The default
56%      is to make R{1} Q7 and R{2} Q9.  R{1} or R.Data for structure output
57%      is a 2x(number of quadrupole in family) array.  The first row is horizontal
58%      tune and the second is vertical.
59%
60%      Units: delta(Tune) / delta(Quadrupole) is set by the .Units field for the quadrupole family
61%             Typically:  Hardware units:  fractional tune / Amp;
62%                         Physics  units:  fractional tune / K;
63%
64%  EXAMPLES
65%  1. Gets 2x2 tune response matrix using the 2 default families
66%     meastuneresp('Display')
67%  2. For all quad in model
68%     RTune = meastuneresp({'Q1','Q2','Q3','Q4','Q5','Q6','Q7','Q8','Q9','Q10'}, 'Model')
69%
70%  NOTES
71%  1. 'Physics' does not work at SOLEIL since polynomial fit does not work for small current !!!
72%
73%  See Also gettune, steptune, settune
74
75%% TODO Correction for SOLEIL and use of Physics option
76
77%
78%  Written by Gregory Portmann and Jeff Corbett
79
80
81% Initialize
82ActuatorFamily = findmemberof('Tune Corrector')';
83if isempty(ActuatorFamily)
84    ActuatorFamily = {'Q7','Q9'};
85end
86
87%ActuatorDelta = {getfamilydata('Q9','Setpoint','DeltaRespMat'),getfamilydata('Q10','Setpoint','DeltaRespMat')};
88ActuatorDelta = {1,1};
89
90ModulationMethod = 'unipolar';
91DirectoryName = [];
92WaitFlag = 10;
93ExtraDelay = 0;
94StructOutputFlag = 0;
95MatrixFlag = 1;
96DisplayFlag = 1;
97ArchiveFlag = -1;
98FileName = -1;
99ModeFlag = '';  % model, online, manual, or '' for default mode
100UnitsFlag = ''; % hardware, physics, or '' for default units
101TimeStamp = clock;
102
103InputFlags = {};
104for i = length(varargin):-1:1
105    if isstruct(varargin{i})
106        % Ignore structures
107    elseif iscell(varargin{i})
108        % Ignore cells
109    elseif strcmpi(varargin{i},'Struct')
110        StructOutputFlag = 1;
111        MatrixFlag = 0;
112        varargin(i) = [];
113    elseif strcmpi(varargin{i},'Numeric')
114        StructOutputFlag = 0;
115        NumericOutputFlag = 1;
116        varargin(i) = [];
117    elseif strcmpi(varargin{i},'Matrix')
118        MatrixFlag = 1;
119        StructOutputFlag = 0;
120        NumericOutputFlag = 1;
121        varargin(i) = [];
122    elseif strcmpi(varargin{i},'Archive')
123        ArchiveFlag = 1;
124        if length(varargin) > i
125            % Look for a filename as the next input
126            if ischar(varargin{i+1})
127                FileName = varargin{i+1};
128                varargin(i+1) = [];
129            end
130        end
131        varargin(i) = [];
132    elseif strcmpi(varargin{i},'NoArchive')
133        ArchiveFlag = 0;
134        varargin(i) = [];
135    elseif strcmpi(varargin{i},'unipolar')
136        ModulationMethod = 'unipolar';
137        varargin(i) = [];
138    elseif strcmpi(varargin{i},'bipolar')
139        ModulationMethod = 'bipolar';
140        varargin(i) = [];
141    elseif strcmpi(varargin{i},'Model')
142        ModeFlag = varargin{i};
143        InputFlags = [InputFlags varargin(i)];
144        varargin(i) = [];
145    elseif strcmpi(varargin{i},'Simulator')
146        ModeFlag = varargin{i};
147        InputFlags = [InputFlags varargin(i)];
148        varargin(i) = [];
149    elseif strcmpi(varargin{i},'Online')
150        ModeFlag = varargin{i};
151        InputFlags = [InputFlags varargin(i)];
152        varargin(i) = [];
153    elseif strcmpi(varargin{i},'Manual')
154        ModeFlag = varargin{i};
155        InputFlags = [InputFlags varargin(i)];
156        varargin(i) = [];
157    elseif strcmpi(varargin{i},'Physics')
158        UnitsFlag = varargin{i};
159        InputFlags = [InputFlags varargin(i)];
160        varargin(i) = [];
161    elseif strcmpi(varargin{i},'Hardware')
162        UnitsFlag = varargin{i};
163        InputFlags = [InputFlags varargin(i)];
164        varargin(i) = [];
165    elseif strcmpi(varargin{i},'NoDisplay')
166        DisplayFlag = 0;
167        varargin(i) = [];
168    elseif strcmpi(varargin{i},'Display')
169        DisplayFlag = 1;
170        varargin(i) = [];
171    end
172end
173
174if length(varargin) >= 1
175    ActuatorFamily = varargin{1}; 
176end
177
178if length(varargin) >= 2
179    ActuatorDeviceList = varargin{2};
180else
181    if iscell(ActuatorFamily)
182        for i = 1:length(ActuatorFamily)
183            ActuatorDeviceList{i} = [];
184        end
185    else
186        ActuatorDeviceList = [];
187    end
188end
189
190if length(varargin) >= 3
191    ActuatorDelta = varargin{3}; 
192else
193    if iscell(ActuatorFamily)
194        for i = 1:length(ActuatorFamily)
195            ActuatorDelta{i} = [];
196        end
197    else
198        ActuatorDelta = [];
199    end
200end
201
202% Force to be a cells
203if ~iscell(ActuatorFamily)
204    ActuatorFamily = {ActuatorFamily};
205end
206if ~iscell(ActuatorDeviceList)
207    ActuatorDeviceList = {ActuatorDeviceList};
208end
209if ~iscell(ActuatorDelta)
210    ActuatorDelta = {ActuatorDelta};
211end
212
213if length(varargin) >= 4
214    ModulationMethod = varargin{4}; 
215end
216
217% WaitFlag input
218if length(varargin) >= 5
219    WaitFlag = varargin{5};
220end
221if isempty(WaitFlag) || WaitFlag == -3
222    WaitFlag = 2.2*getfamilydata('TuneDelay');
223end
224if isempty(WaitFlag)
225    WaitFlag = input('   Delay for Tune Measurement (Seconds, Keyboard Pause = -4, or Manual Tune Input = -5) = ');
226end
227
228if length(varargin) >= 6
229    FileName = varargin{6}; 
230end
231if length(varargin) >= 7
232    if isempty(varargin{7})
233        % Use default
234        DirectoryName = getfamilydata('Directory', 'TuneResponse');
235    elseif ischar(varargin{7})
236        DirectoryName = varargin{7};
237    else
238        % Empty DirectoryName mean it will only be used if FileName is empty
239        DirectoryName = [];
240    end
241end
242
243% Look for ExtraDelay
244if length(varargin) >= 8
245    if isempty(varargin{8})
246        % Use default
247    end
248    if isnumeric(varargin{8})
249        ExtraDelay = varargin{8};
250    end
251end
252
253
254% % Check units (default units is based on the actuator)
255% if isempty(UnitsFlag)
256%     UnitsFlag = getfamilydata(ActuatorFamily{1},'Setpoint','Units');
257% end
258% if isempty(UnitsFlag)
259%     error('Unknown Units');
260% end
261
262% % Check mode
263% if isempty(ModeFlag)
264%     ModeFlag = getfamilydata(ActuatorFamily{1},'Setpoint','Mode');
265% end
266% if isempty(ModeFlag)
267%     error('Unknown Mode');
268% end
269
270
271% Change defaults for the model (note: simulator mode mimics online)
272if strcmpi(ModeFlag,'Model')
273    % Only archive data if ArchiveFlag==1 or FileName~=[]
274    if ischar(FileName) || ArchiveFlag == 1
275        ArchiveFlag = 1;   
276    else
277        ArchiveFlag = 0;           
278    end
279   
280    % Only display is it was turned on at the command line
281    if DisplayFlag == 1
282        % Keep DisplayFlag = 1
283    else
284        DisplayFlag = 0;
285    end
286else
287    % Online or Simulator: Archive unless ArchiveFlag was forced to zero
288    if ArchiveFlag ~= 0
289        ArchiveFlag = 1; 
290        if FileName == -1
291            FileName = '';
292        end
293    end
294end
295
296
297% Print setup information
298% if DisplayFlag
299%     if ~strcmpi(ModeFlag,'Model')
300%         fprintf('\n');
301%         fprintf('   MEASTUNERESP measures the tune response to the quadrupole magnet families.\n');
302%         fprintf('   The storage ring lattice and hardware should be setup for properly.\n');
303%         fprintf('   Make sure the following information is correct:\n');
304%         fprintf('   1.  Proper magnet lattice (including skew quadrupoles)\n');
305%         fprintf('   2.  Proper electron beam energy\n');
306%         fprintf('   3.  Proper electron bunch pattern\n');
307%         fprintf('   4.  Tune is functioning or in manual mode\n');
308%         fprintf('   5.  The injection bump magnets off\n\n');
309%     end
310% end   
311
312
313% Browse for filename and directory if using default FileName
314if ArchiveFlag
315    if isempty(FileName)
316        FileName = appendtimestamp(getfamilydata('Default', 'TuneRespFile'));
317        DirectoryName = getfamilydata('Directory', 'TuneResponse');
318        if isempty(DirectoryName)
319            DirectoryName = [getfamilydata('Directory','DataRoot') 'Response', filesep, 'Dispersion', filesep];
320        else
321            % Make sure default directory exists
322            DirStart = pwd;
323            [DirectoryName, ErrorFlag] = gotodirectory(DirectoryName);
324            cd(DirStart);
325        end
326        [FileName, DirectoryName] = uiputfile('*.mat', 'Select a Dispersion Response File', [DirectoryName FileName]);
327        if FileName == 0
328            ArchiveFlag = 0;
329            disp('   Dispersion response measurement canceled.');
330            Rmat = []; OutputFileName='';
331            return
332        end
333        FileName = [DirectoryName, FileName];
334    elseif FileName == -1
335        FileName = appendtimestamp(getfamilydata('Default', 'TuneRespFile'));
336        DirectoryName = getfamilydata('Directory', 'TuneResponse');
337        if isempty(DirectoryName)
338            DirectoryName = [getfamilydata('Directory','DataRoot') 'Response', filesep, 'Dispersion', filesep];
339        end
340        FileName = [DirectoryName, FileName];
341    end
342   
343    % Acquire initial data
344    MachineConfig = getmachineconfig(InputFlags{:});
345end
346
347
348% % Query to begin measurement
349% if DisplayFlag
350%     tmp = questdlg('Begin response matrix measurement?','MEASTUNERESP','YES','NO','YES');
351%     if strcmp(tmp,'NO')
352%         fprintf('   Response matrix measurement aborted\n');
353%         Rmat = [];
354%         return
355%     end
356% end
357
358
359% Acquire initial data
360if StructOutputFlag || ArchiveFlag               
361    X = getx('struct', InputFlags{:});
362    Y = gety('struct', InputFlags{:});
363end   
364
365
366% Begin main loop over actuators
367TimeStart = gettime;
368% TUNE must be a family for this to work
369if DisplayFlag
370    Rmat = measrespmat('TUNE', [1;2], ActuatorFamily, ActuatorDeviceList, ActuatorDelta, ModulationMethod, WaitFlag, ExtraDelay, 'Struct', 'Display', InputFlags{:});
371else
372    Rmat = measrespmat('TUNE', [1;2], ActuatorFamily, ActuatorDeviceList, ActuatorDelta, ModulationMethod, WaitFlag, ExtraDelay, 'Struct', 'NoDisplay', InputFlags{:});
373end
374if StructOutputFlag   
375    for i = 1:size(Rmat,1)
376        for j = 1:size(Rmat,2)
377            if iscell(Rmat)
378                Rmat{i,j}.DataDescriptor = 'Tune Response Matrix';
379                Rmat{i,j}.CreatedBy = 'meastuneresp';
380               
381                Rmat{i,j}.X = X;
382                Rmat{i,j}.Y = Y;
383            else
384                Rmat(i,j).DataDescriptor = 'Tune Response Matrix';
385                Rmat(i,j).CreatedBy = 'meastuneresp';
386               
387                Rmat(i,j).X = X;
388                Rmat(i,j).Y = Y;
389            end
390        end
391    end
392end
393
394
395% For one family inputs, there is no need for a cell output (probably already done in measrespmat)
396if length(Rmat) == 1 && iscell(Rmat)
397    Rmat = Rmat{1};
398end
399
400
401% Save data in the proper directory
402if ArchiveFlag || ischar(FileName)
403    [DirectoryName, FileName, Ext] = fileparts(FileName);
404    DirStart = pwd;
405    [DirectoryName, ErrorFlag] = gotodirectory(DirectoryName);
406    if ErrorFlag
407        fprintf('\n   There was a problem getting to the proper directory!\n\n');
408    end
409    save(FileName, 'Rmat','MachineConfig');
410    cd(DirStart);
411    OutputFileName = [DirectoryName, FileName, '.mat'];
412   
413    if DisplayFlag
414        fprintf('   Tune response matrix data (''Rmat'') saved to disk\n');
415        fprintf('   Filename: %s\n', OutputFileName);
416        fprintf('   The total response matrix measurement time: %.2f minutes.\n', (gettime-TimeStart)/60);
417    end
418end
419
420
421% Put the data part in Rmat
422if ~StructOutputFlag
423    if length(ActuatorFamily) == 1
424        Rmat = Rmat.Data;
425    else
426        for i = 1:size(Rmat,1)
427            for j = 1:size(Rmat,2)
428                Rmat{i,j} = Rmat{i,j}.Data;
429            end
430        end
431    end
432end
433
434if MatrixFlag && StructOutputFlag
435    error('Cannot ask for a matrix and a structure output.');
436end
437
438
439if MatrixFlag
440    if length(ActuatorFamily) == 1
441        R = sum(Rmat,2);
442    else
443        if size(Rmat,1) == 1
444            for j = 1:size(Rmat,2)
445                R(:,j) = sum(Rmat{1,j},2);
446            end
447        else
448            error('Tune response matrix cell array has more than one row (which is very odd)');
449        end
450    end
451    Rmat = R;
452end
453
454
455
456
457
458% % TUNE is not a family, then use gettune
459%
460% % Force to be a column vector
461% % ActuatorDelta = {getfamilydata('QF','Setpoint','DeltaRespMat'),getfamilydata('QD','Setpoint','DeltaRespMat')};
462% ActuatorDelta{i} = ActuatorDelta{i}(:);
463%
464% Rmat(i).Data = [];
465% Rmat(i).Monitor.FamilyName = 'TUNE';
466% Rmat(i).Actuator = getsp(ActuatorFamily{i}, ActuatorDeviceList{i}, 'struct');
467% Rmat(i).ActuatorDelta = ActuatorDelta{i};
468% Rmat(i).GeV = bend2gev(InputFlags{:});
469% Rmat(i).TimeStamp = TimeStamp;
470% if strcmp(lower(family2units(ActuatorFamily{i},'Setpoint')),'hardware')
471%     Rmat(i).Units = 'Hardware';
472%     Rmat(i).UnitsString = '1/Amp';
473%     Rmat(i).Monitor.Units = 'Hardware';
474% else
475%     Rmat(i).Units = 'Physics';
476%     Rmat(i).UnitsString = '1/K';
477%     Rmat(i).Monitor.Units = 'Physics';
478% end
479% Rmat(i).ModulationMethod = 'Unipolar';
480% Rmat(i).WaitFlag = WaitFlag;
481% Rmat(i).DataDescriptor = 'Tune Response Matrix';
482% Rmat(i).CreatedBy = 'meastuneresp';
483%
484% InitActuator = Rmat(i).Actuator.Data;
485%
486% % Acquire initial data
487% if StructOutputFlag               
488%     Rmat(i).X = getx('struct');
489%     Rmat(i).Y = gety('struct');
490%     Rmat(i).DCCT = getdcct;
491% end   
492%
493% % No actuator change for first point
494% if DisplayFlag
495%     fprintf('   Initial actuator value for %s is %+f\n', ActuatorFamily{i}, InitActuator(1));
496%     fprintf('   No change to actuator');
497%     drawnow;
498% end
499%
500% % Acquire data
501% if DisplayFlag
502%     fprintf(', recording data point #1\n');
503%     drawnow;
504% end
505%
506% % Wait for tune monitor to have fresh data
507% if WaitFlag >= 0
508%     fprintf('   Pausing %f seconds for the tune measurement.\n', WaitFlag);
509%     sleep(WaitFlag);
510%     Rmat(i).Monitor = gettune('struct');
511% elseif WaitFlag == -4
512%     tmp = input('   Hit return when the tune measurement is ready. ');
513%     Rmat(i).Monitor = gettune('struct');
514% elseif WaitFlag == -5
515%     Rmat(i).Monitor.Data(1,1) = input('      Input the horizontal tune = ');
516%     Rmat(i).Monitor.Data(2,1) = input('      Input the  vertical  tune = ');
517%     Rmat(i).Monitor.DeviceList = [1 1;1 2];
518%     Rmat(i).Monitor.ElementList = [1; 2];
519%     Rmat(i).Monitor.Field = 'Monitor';
520%     Rmat(i).Monitor.Status = [1;1];
521%     Rmat(i).Monitor.Mode: 'Unknown';
522%     Rmat(i).Monitor.t = 0;
523%     Rmat(i).Monitor.tout = NaN;
524%     Rmat(i).Monitor.TimeStamp = clock;
525%     Rmat(i).Monitor.Units = 'Unknown';
526%     Rmat(i).Monitor.UnitsString = 'Fractional Tune';
527%     Rmat(i).Monitor.DataDescriptor = 'Tune';
528%     CreatedBy = 'gettune';
529% else
530%     error('Tune delay method unknown');
531% end
532% TuneMinus = Rmat(i).Monitor.Data;
533%
534% % Step actuator up
535% if DisplayFlag
536%     fprintf('\n   Changing actuator by %+f', ActuatorDelta{i}(1));
537%     drawnow;           
538% end
539% setsp(ActuatorFamily{i}, InitActuator+ActuatorDelta{i}, ActuatorDeviceList{i}, WaitFlag);
540%
541% % Acquire data
542% if DisplayFlag
543%     fprintf(', recording data point #2\n');
544%     drawnow;
545% end
546%
547% % Wait for tune monitor to have fresh data
548% if WaitFlag >= 0
549%     fprintf('   Pausing %f seconds for the tune measurement.\n', WaitFlag);
550%     sleep(WaitFlag);
551%     TunePlus = gettune;
552% elseif WaitFlag == -4
553%     tmp = input('   Hit return when the tune measurement is ready. ');
554%     TunePlus = gettune;
555% elseif WaitFlag == -5
556%     TunePlus(1,2) = input('      Input the horizontal tune = ');
557%     TunePlus(2,2) = input('      Input the  vertical  tune = ');
558% else
559%     error('Tune delay method unknown');
560% end
561%
562% % Restore actuators
563% setsp(ActuatorFamily{i}, InitActuator, ActuatorDeviceList{i}, WaitFlag);
564% if DisplayFlag
565%     fprintf('   Reset actuator %s \n\n', ActuatorFamily{i});
566%     drawnow;
567% end
568%
569% % Compute response matrix columns
570% % For each magnet:  1. Divide by the change in amperes [Tune / Ampere]
571% %                   2. Scale each magnet by its fractional contribution in physics units
572% if strcmp(lower(family2units(ActuatorFamily{i},'Setpoint')),'hardware')
573%     DeltaPhysics = hw2physics(ActuatorFamily{i}, 'Setpoint', InitActuator+ActuatorDelta{i}, ActuatorDeviceList{i}) - hw2physics(ActuatorFamily{i}, 'Setpoint', InitActuator, ActuatorDeviceList{i});
574% else
575%     DeltaPhysics = ActuatorDelta{i};
576% end
577%
578% % In order to backout the tune response at each magnet, assume that
579% % the tune response at each magnet is equal in physics units. 
580% DelTunePerK = (TunePlus-TuneMinus) / sum(DeltaPhysics);
581%
582% % Expand to each magnet
583% Rmat(i).Data = DelTunePerK * ones(1,length(DeltaPhysics));
584%
585% % When in hardware unit convert to delta tune / ampere
586% if strcmp(lower(family2units(ActuatorFamily{i},'Setpoint')),'hardware')
587%     KPerAmp = DeltaPhysics ./ ActuatorDelta{i};
588%     for j = 1:length(DeltaPhysics)
589%         Rmat(i).Data(:,j) = KPerAmp(j) * Rmat(i).Data(:,j);
590%     end
591% end
Note: See TracBrowser for help on using the repository browser.