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

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

Initial import--MML version from SOLEIL@2013

File size: 45.5 KB
Line 
1function [Rmat, OutputFileName] = measbpmresp(varargin)
2%MEASBPMRESP - Measures the BPM response matrix in the horizontal and vertical planes
3%
4%  For family name, device list inputs:
5%  [R, FileName] = measbpmresp(BPMxFamily, BPMxList, BPMyFamily, BPMyList, HCMFamily, HCMList, VCMFamily, VCMList, HCMKicks, VCMKicks, ModulationMethod, WaitFlag, FileName, DirectoryName, ExtraDelay)
6%
7%  For data structure inputs:
8%  [R, FileName] = measbpmresp(BPMxStruct, BPMyStruct, HCMStruct, VCMStruct, HCMKicks, VCMKicks, ModulationMethod, WaitFlag, FileName, DirectoryName, ExtraDelay)
9%
10%  INPUTS
11%  1. BPMxFamily       - BPMx family name {Default: gethbpmfamily}
12%     BPMxDeviceList   - BPMx device list {Default: all devices with good status}
13%     or
14%     BPMxStruct can replace BPMxFamily and BPMxList
15%
16%  2. BPMyFamily       - BPMy family name {Default: getvbpmfamily}
17%     BPMyDeviceList   - BPMy device list {Default: all devices with good status}
18%     or
19%     BPMyStruct can replace BPMyFamily and BPMyList
20%
21%  3. HCMFamily       - HCM family name {Default: gethcmfamily}
22%     HCMDeviceList   - HCM device list {Default: all devices with good status}
23%     or
24%     HCMStruct can replace HCMFamily and HCMList
25%
26%  4. VCMFamily       - VCM family name {Default: getvcmfamily}
27%     VCMDeviceList   - VCM device list {Default: all devices with good status}
28%     or
29%     VCMStruct can replace VCMFamily and VCMList
30%
31%  5. HCMKicks - Change in HCM correctors {Default: getfamilydata(HCMFamily,'Setpoint','DeltaRespMat',HCMDeviceList), then .05 mrad}
32%  6. VCMKicks - Change in VCM correctors {Default: getfamilydata(VCMFamily,'Setpoint','DeltaRespMat',VCMDeviceList), then .05 mrad}
33%
34%  7. ModulationMethod - Method for changing the ActuatorFamily
35%                       'bipolar' changes the ActuatorFamily by +/- ActuatorDelta/2 on each step {Default}
36%                       'unipolar' changes the ActuatorFamily from 0 to ActuatorDelta on each step
37%
38%  8. WaitFlag - (see setpv for WaitFlag definitions) {Default: []}
39%                WaitFlag = -5 will override gets to manual mode
40%
41%  9. Optional input to change the default filename and directory
42%     FileName - Filename for the response matrix data
43%                (Empty prompts for a filename) 
44%     DirectoryName - Directory name to store the response matrix data file
45%     Note: a. FileName can include the path if DirectoryName is not used
46%           b. For model response matrices, FileName must exist for a file save
47%           c. The 'Achive' flag is another way to input the filename
48%
49%  10. ExtraDelay - extra time delay [seconds] after a setpoint change
50%
51%  11. 'Struct'  - Output will be a response matrix structure {Default for     data structure inputs}
52%      'Numeric' - Output will be a numeric matrix            {Default for non-data structure inputs}
53%
54%  12. Optional override of the units:
55%      'Physics'  - Use physics  units
56%      'Hardware' - Use hardware units
57%
58%  13. Optional override of the mode:
59%      'Online'    - Set/Get data online 
60%      'Model'     - Set/Get data directly from AT (uses locoresponsematrix)
61%      'Simulator' - Set/Get data on the simulated accelerator using AT (ie, same commands as 'Online')
62%      'Manual'    - Set/Get data manually
63%
64%  14. 'Display'   - Prints status information to the command window {Default}
65%      'NoDisplay' - Nothing is printed to the command window
66%
67%  15. 'NoArchive' - No file archive
68%      'Archive'   - Save the response matrix data to \<Directory.BPMResponse>\<BPMRespFile><Date><Time>.mat
69%                    To change the filename, included the filename after the 'Archive', '' to browse
70%
71%  16. 'MinimumBeamCurrent' - Minimum beam current before prompting for a refill
72%                             The current (as returned by getdcct) must follow the flag.
73%                             measbpmresp('MinimumBeamCurrent', 32.1)
74%                             will pause at a beam current of 32.1 and prompt for a refill.
75%
76%  17. Optional inputs when computing model response matrices:
77%      'FixedPathLength' or 'FixedMomentum' - hold the path length or momentum fixed  {Default: 'FixedPathLength'}
78%      'Full' or 'Linear' - use full nonlinear model or linear approximation (faster) {Default: 'Linear'}
79%      Note: The ModulationMethod input (7) is also used for the model calculation.
80%
81%  OUTPUTS
82%  1. R = Orbit response matrix (delta(orbit)/delta(Kick))
83%
84%     Numeric Output:
85%       R = [xx xy
86%            yx yy]
87%
88%     Stucture Output:
89%     R(BPM Plane, Corrector Plane) - 2x2 struct array
90%     R(1,1).Data=xx;  % Kick x, look x
91%     R(2,1).Data=yx;  % Kick x, look y
92%     R(1,2).Data=xy;  % Kick y, look x
93%     R(2,2).Data=yy;  % Kick y, look y
94%           
95%     R(Monitor, Actuator).Data - Response matrix
96%                         .Monitor  - BPM data structure (starting orbit)
97%                         .Monitor1 - BPM matrix (first  data point)
98%                         .Monitor2 - BPM matrix (second data point)
99%                         .Actuator - Corrector data structure
100%                         .ActuatorDelta - Corrector kick vector
101%                         .GeV - Electron beam energy
102%                         .ModulationMethod - 'unipolar' or 'bipolar'
103%                         .WaitFlag - Wait flag used when acquiring data
104%                         .ExtraDelay - Extra time delay
105%                         .TimeStamp
106%                         .CreatedBy
107%                         .DCCT
108%
109%  2. FileName = File name (including directory) where the data was saved (if applicable)
110%                (a machine configuration structure is saved in the data file as well)
111%
112%  NOTES
113%  1. [] can be used on any input to obtain the default setting.
114%     However, most inputs can be left out altogether to get the default.
115%  2. For Mode = 'Model':
116%     a. AT family names (or 'All') can be used and DeviceList is ignored
117%     b. There is a lot of flexibility for getting response matrices, for instance,
118%        R = measbpmresp('QF', 'QD', 'HCM', 'VCM', 'Model', 'Physics');
119%        is the response matrix from the correctors to orbit at the sextupoles.
120%        The units when using nonstandard families for BPMs is always 'physics', meter/radian. 
121%  3. Cell inputs are not allowed.
122%  4. BPM roll and crunch and corrector magnet roll errors are included only if they are
123%     in the AT model (field .GCR for BPMs and .Roll for correctors).
124%     BPM and corrector magnet gains are included in hardware units (not physics units).
125%  5. This function measures response matrices from 2 BPM families to 2 corrector families. 
126%     If only one family is needed then use measrespmat.
127%
128%  EXAMPLES
129%  1. Default:
130%       R = measbpmresp;
131%       is the same as,
132%       R = measbpmresp('BPMx', 'BPMy', 'HCM', 'VCM', 'Online', 'Bipolar', 'Numeric', 'Archive');
133%
134%  2. Default using the model:
135%       R = measbpmresp('Model');
136%       is the same as,
137%       R = measbpmresp('BPMx', 'BPMy', 'HCM', 'VCM', 'Model', 'Bipolar', 'Numeric', 'NoArchive', 'FixedPathLength', 'Linear');
138%
139%  3. Compare measured (or Default) and model BPM response
140%     Rmeas  = getbpmresp;
141%     Rmodel = measbpmresp('Model');
142%     subplot(2,1,1);
143%     surf(Rmeas);  title('Default BPM Response'); xlabel('BPM #'); ylabel('CM #'); zlabel('[mm/amp]');
144%     subplot(2,1,2);
145%     surf(Rmeas-Rmodel);  title('Default - Model BPM Response'); xlabel('BPM #'); ylabel('CM #'); zlabel('[mm/amp]');
146%
147%  See also getbpmresp, measrespmat, meastuneresp, measchroresp
148
149%
150%  Written by Greg Portmann
151%  Modified by Laurent S. Nadolski - Add check list before starting the measurement.
152
153
154% Initialize defaults
155BPMxFamily = gethbpmfamily;
156if isempty(BPMxFamily)
157    error('"BPMx" needs to be a MemberOf some family.');
158end
159BPMxList = [];
160
161BPMyFamily = getvbpmfamily;
162if isempty(BPMyFamily)
163    error('"BPMy" needs to be a MemberOf some family.');
164end
165BPMyList = [];
166
167HCMFamily = gethcmfamily;
168if isempty(HCMFamily)
169    error('"HCM" needs to be a MemberOf some family.');
170end
171HCMList = [];
172HCMKicks = [];
173Default2HCMKick = .05e-3;  % Radians, if getfamilydata(HCMFamily,'Setpoint','DeltaRespMat') is empty
174
175VCMFamily = getvcmfamily;
176if isempty(VCMFamily)
177    error('"VCM" needs to be a MemberOf some family.');
178end
179VCMList = [];
180VCMKicks = [];
181Default2VCMKick = .05e-3;  % Radians, if getfamilydata(VCMFamily,'Setpoint','DeltaRespMat') is empty
182ModulationMethod = 'bipolar';
183
184% Map MML to LOCO naming
185if strcmpi(ModulationMethod, 'bipolar')
186    LOCORespFlags.ResponseMatrixMeasurement = 'Bidirectional';   % 'oneway'' or ''bidirectional'
187else
188    LOCORespFlags.DispersionMeasurement     = 'Bidirectional';
189end
190if isstoragering
191    LOCORespFlags.ResponseMatrixCalculator  = 'Linear';
192    LOCORespFlags.ClosedOrbitType           = 'fixedpathlength';
193    LOCORespFlags.MachineType               = 'StorageRing';
194else
195    % Full is usually as fast as Linear for transport lines
196    LOCORespFlags.ResponseMatrixCalculator  = 'full';
197    LOCORespFlags.ClosedOrbitType           = 'fixedmomentum';
198    LOCORespFlags.MachineType               = 'Transport';
199end
200
201WaitFlag = 1.0; % Delay before taking data
202ExtraDelay = 2.0; % Delay after setting steerer values
203StructOutputFlag = 0;
204NumericOutputFlag = 0;
205DisplayFlag = -1;
206ArchiveFlag = -1;
207FileName = -1;
208DirectoryName = '';
209ModeFlag = '';  % model, online, manual, or '' for default mode
210UnitsFlag = ''; % hardware, physics, or '' for default units
211
212InputFlags = {};
213DCCTFlag = {};
214for i = length(varargin):-1:1
215    if isstruct(varargin{i})
216        % Ignore structures
217    elseif iscell(varargin{i})
218        % Ignore cells
219    elseif strcmpi(varargin{i},'Struct')
220        StructOutputFlag = 1;
221        varargin(i) = [];
222    elseif strcmpi(varargin{i},'Numeric')
223        StructOutputFlag = 0;
224        NumericOutputFlag = 1;
225        varargin(i) = [];
226    elseif strcmpi(varargin{i},'Model')
227        ModeFlag = varargin{i};
228        InputFlags = [InputFlags varargin(i)];
229        varargin(i) = [];
230    elseif strcmpi(varargin{i},'Simulator')
231        ModeFlag = varargin{i};
232        InputFlags = [InputFlags varargin(i)];
233        varargin(i) = [];
234    elseif strcmpi(varargin{i},'Online')
235        ModeFlag = varargin{i};
236        InputFlags = [InputFlags varargin(i)];
237        varargin(i) = [];
238    elseif strcmpi(varargin{i},'Manual')
239        ModeFlag = varargin{i};
240        InputFlags = [InputFlags varargin(i)];
241        varargin(i) = [];
242    elseif strcmpi(varargin{i},'Physics')
243        UnitsFlag = varargin{i};
244        InputFlags = [InputFlags varargin(i)];
245        varargin(i) = [];
246    elseif strcmpi(varargin{i},'Hardware')
247        UnitsFlag = varargin{i};
248        InputFlags = [InputFlags varargin(i)];
249        varargin(i) = [];
250    elseif strcmpi(varargin{i},'Archive')
251        ArchiveFlag = 1;
252        if length(varargin) > i
253            % Look for a filename as the next input
254            if ischar(varargin{i+1})
255                FileName = varargin{i+1};
256                varargin(i+1) = [];
257            end
258        end
259        varargin(i) = [];
260    elseif strcmpi(varargin{i},'NoArchive')
261        ArchiveFlag = 0;
262        varargin(i) = [];
263    elseif strcmpi(varargin{i},'NoDisplay')
264        DisplayFlag = 0;
265        InputFlags = [InputFlags varargin(i)];
266        varargin(i) = [];
267    elseif strcmpi(varargin{i},'Display')
268        DisplayFlag = 1;
269        InputFlags = [InputFlags varargin(i)];
270        varargin(i) = [];
271
272    elseif strcmpi(varargin{i},'unipolar') || strcmpi(varargin{i},'oneway')
273        ModulationMethod = 'unipolar';
274        LOCORespFlags.ResponseMatrixMeasurement = 'oneway';
275        varargin(i) = [];
276    elseif strcmpi(varargin{i},'bipolar') || strcmpi(varargin{i},'bidirectional')
277        ModulationMethod = 'bipolar';
278        LOCORespFlags.ResponseMatrixMeasurement = 'bidirectional';
279        varargin(i) = [];
280
281    elseif strcmpi(varargin{i},'FixedPathLength')
282        LOCORespFlags.ClosedOrbitType = 'FixedPathLength';
283        varargin(i) = [];
284    elseif strcmpi(varargin{i},'FixedMomentum')
285        LOCORespFlags.ClosedOrbitType = 'FixedMomentum';
286        varargin(i) = [];
287    elseif strcmpi(varargin{i},'Linear')
288        LOCORespFlags.ResponseMatrixCalculator = 'Linear';
289        varargin(i) = [];
290    elseif strcmpi(varargin{i},'Full')
291        LOCORespFlags.ResponseMatrixCalculator = 'Full';
292        varargin(i) = [];
293
294    elseif strcmpi(varargin{i},'MinimumBeamCurrent')
295        DCCTFlag = [varargin(i) varargin(i+1)];
296        varargin(i+1) = [];
297        varargin(i)   = [];
298    end
299end
300
301%%%%%%%%%%%%%%%%
302% Parse Inputs %
303%%%%%%%%%%%%%%%%
304
305% Look for BPMx family info
306if length(varargin) >= 1
307    if isstruct(varargin{1})
308        BPMxFamily = varargin{1}.FamilyName;
309        BPMxList = varargin{1}.DeviceList;
310
311        % For structure inputs, units are determined by the first input
312        if isempty(UnitsFlag)
313            UnitsFlag = varargin{1}.Units;
314        end
315
316        varargin(1) = [];
317       
318        % Only change StructOutputFlag if 'Numeric' is not on the input line
319        if ~NumericOutputFlag
320            StructOutputFlag = 1;
321        end
322    elseif ischar(varargin{1})
323        BPMxFamily = varargin{1};
324        varargin(1) = [];
325        if length(varargin) >= 1
326            if isnumeric(varargin{1})
327                BPMxList = varargin{1};
328                varargin(1) = [];
329            end
330        end
331    elseif isnumeric(varargin{1})
332        BPMxList = varargin{1};
333        varargin(1) = [];
334    end
335end
336if isempty(BPMxList)
337    BPMxList = family2dev(BPMxFamily, 1);
338end
339
340% Look for BPMy family info
341if length(varargin) >= 1
342    if isstruct(varargin{1})
343        BPMyFamily = varargin{1}.FamilyName;
344        BPMyList = varargin{1}.DeviceList;
345        varargin(1) = [];
346        if ~NumericOutputFlag
347            StructOutputFlag = 1; % Only change StructOutputFlag if 'Numeric' is not on the input line
348        end
349    elseif ischar(varargin{1})
350        BPMyFamily = varargin{1};
351        varargin(1) = [];
352        if length(varargin) >= 1
353            if isnumeric(varargin{1})
354                BPMyList = varargin{1};
355                varargin(1) = [];
356            end
357        end
358    elseif isnumeric(varargin{1})
359        BPMyList = varargin{1};
360        varargin(1) = [];
361    end
362end
363if isempty(BPMyList)
364    BPMyList = family2dev(BPMyFamily, 1);
365end
366
367% Look for HCM family info
368if length(varargin) >= 1
369    if isstruct(varargin{1})
370        HCMFamily = varargin{1}.FamilyName;
371        HCMList = varargin{1}.DeviceList;
372        varargin(1) = [];
373        if ~NumericOutputFlag
374            StructOutputFlag = 1; % Only change StructOutputFlag if 'Numeric' is not on the input line
375        end
376    elseif ischar(varargin{1})
377        HCMFamily = varargin{1};
378        varargin(1) = [];
379        if length(varargin) >= 1
380            if isnumeric(varargin{1})
381                HCMList = varargin{1};
382                varargin(1) = [];
383            end
384        end
385    elseif isnumeric(varargin{1})
386        HCMList = varargin{1};
387        varargin(1) = [];
388    end
389end
390if isempty(HCMList)
391    HCMList = family2dev(HCMFamily, 1);
392end
393
394% Look for VCM family info
395if length(varargin) >= 1
396    if isstruct(varargin{1})
397        VCMFamily = varargin{1}.FamilyName;
398        VCMList = varargin{1}.DeviceList;
399        varargin(1) = [];
400        if ~NumericOutputFlag
401            StructOutputFlag = 1; % Only change StructOutputFlag if 'Numeric' is not on the input line
402        end
403    elseif ischar(varargin{1})
404        VCMFamily = varargin{1};
405        varargin(1) = [];
406        if length(varargin) >= 1
407            if isnumeric(varargin{1})
408                VCMList = varargin{1};
409                varargin(1) = [];
410            end
411        end
412    elseif isnumeric(varargin{1})
413        VCMList = varargin{1};
414        varargin(1) = [];
415    end
416end
417if isempty(VCMList)
418    VCMList = family2dev(VCMFamily, 1);
419end
420
421% Look for HCMKicks
422if length(varargin) >= 1
423    if isempty(varargin{1})
424        % Use default
425        varargin(1) = [];
426    elseif isnumeric(varargin{1})
427        HCMKicks = varargin{1};
428        varargin(1) = [];
429    end
430end
431
432% Look for VCMKicks
433if length(varargin) >= 1
434    if isempty(varargin{1})
435        % Use default
436        varargin(1) = [];
437    elseif isnumeric(varargin{1})
438        VCMKicks = varargin{1};
439        varargin(1) = [];
440    end
441end
442
443% ModulationMethod has already been searched for
444% % Look for ModulationMethod
445% if length(varargin) >= 1
446%     if isempty(varargin{1})
447%         % Use default
448%         varargin(1) = [];
449%     end
450%     if ischar(varargin{1})
451%         ModulationMethod = varargin{1};
452%         varargin(1) = [];
453%     end
454% end
455if ~strcmpi(ModulationMethod, 'unipolar') && ~strcmpi(ModulationMethod, 'bipolar')
456    error('ModulationMethod must be ''unipolar'' or ''bipolar''');
457end
458
459
460% Look for WaitFlag
461if length(varargin) >= 1
462    if isempty(varargin{1})
463        % Use default
464        varargin(1) = [];
465    end
466    if isnumeric(varargin{1})
467        WaitFlag = varargin{1};
468        varargin(1) = [];
469    end
470end
471
472% FileName and DirectoryName
473if length(varargin) >= 1
474    if isempty(varargin{1})
475        % Use default
476        FileName = '';
477        varargin(1) = [];
478    end
479    if ischar(varargin{1})
480        FileName = varargin{1};
481        varargin(1) = [];
482    end
483end
484if length(varargin) >= 1
485    if isempty(varargin{1})
486        % Use default
487        DirectoryName = getfamilydata('Directory', 'BPMResponse');
488        FileName = [DirectoryName, FileName];
489        varargin(1) = [];
490    elseif ischar(varargin{1})
491        DirectoryName = varargin{1};
492        if strcmp(DirectoryName, filesep)
493            FileName = [DirectoryName, FileName];
494        else
495            FileName = [DirectoryName, filesep, FileName];
496        end
497        varargin(1) = [];
498    end
499end
500
501% Look for ExtraDelay
502if length(varargin) >= 1
503    if isempty(varargin{1})
504        % Use default
505        varargin(1) = [];
506    end
507    if isnumeric(varargin{1})
508        ExtraDelay = varargin{1};
509        varargin(1) = [];
510    end
511end
512
513% Check units
514if isempty(UnitsFlag)
515    if strcmpi(getfamilydata(BPMxFamily,'Monitor','Units'), getfamilydata(BPMyFamily,'Monitor','Units'))
516        UnitsFlag = getfamilydata(BPMxFamily,'Monitor','Units');
517    else
518        error('Mixed Units for orbits');
519    end
520end
521if isempty(UnitsFlag)
522    error('Unknown Units');
523end
524
525% Check mode
526if isempty(ModeFlag)
527    if strcmpi(getfamilydata(BPMxFamily,'Monitor','Mode'), getfamilydata(BPMyFamily,'Monitor','Mode'))
528        %ModeFlag = getfamilydata(BPMxFamily,'Monitor','Mode');
529    else
530        error('Mixed Mode for orbits');
531    end
532    if strcmpi(getfamilydata(HCMFamily,'Monitor','Mode'), getfamilydata(VCMFamily,'Monitor','Mode'))
533        ModeFlag = getfamilydata(HCMFamily,'Monitor','Mode');
534    else
535        error('Mixed Mode for correctors');
536    end
537end
538if isempty(ModeFlag)
539    error('Unknown Mode');
540end
541% Input parsing complete
542
543
544% Starting time
545TimeStart = gettime;
546
547
548% Change defaults for the model (note: simulator mode mimics online)
549if strcmpi(ModeFlag,'Model')
550    % Only archive data if ArchiveFlag==1 or FileName~=[]
551    if ischar(FileName) || ArchiveFlag == 1
552        ArchiveFlag = 1;   
553    else
554        ArchiveFlag = 0;           
555    end
556   
557    % Only display is it was turned on at the command line
558    if DisplayFlag == 1
559        % Keep DisplayFlag = 1
560    else
561        DisplayFlag = 0;
562    end
563else
564    % Online or Simulator: Archive unless ArchiveFlag was forced to zero
565    if ArchiveFlag ~= 0
566        ArchiveFlag = 1;
567        if FileName == -1
568            FileName = '';
569        end
570    end   
571end
572
573% % Print setup information
574% if DisplayFlag
575%     if ~strcmpi(ModeFlag,'Model')
576%         fprintf('\n');
577%         fprintf('   MEASBPMRESP measures the BPM response matrix for both HCM & VCM corrector families.\n');
578%         fprintf('   The storage ring lattice and hardware should be setup for accurate orbit measurements.\n');
579%         fprintf('   Make sure the following information is correct:\n');
580%         fprintf('   1.  Proper magnet lattice\n');
581%         fprintf('   2.  Proper electron beam energy\n');
582%         fprintf('   3.  Proper electron bunch pattern\n');
583%         fprintf('   4.  BPMs are functioning properly (calibrated, sample rate, etc.)\n');
584%         fprintf('   5.  Corrector magnets are working\n');
585%         fprintf('   6.  The injection bump magnets off\n');
586%         fprintf('   7.  Corrector Settle Time WaitFlag=%f, Extra BPM Delay=%f\n', WaitFlag, ExtraDelay);
587%         fprintf('   9.  Modulation Method: %s\n', ModulationMethod);
588%     end
589% end
590
591
592if ArchiveFlag
593    if isempty(FileName)
594        FileName = appendtimestamp(getfamilydata('Default', 'BPMRespFile'));
595        DirectoryName = getfamilydata('Directory', 'BPMResponse');
596        if isempty(DirectoryName)
597            DirectoryName = [getfamilydata('Directory','DataRoot'), 'Response', filesep, 'BPM', filesep];
598        else
599            % Make sure default directory exists
600            DirStart = pwd;
601            [DirectoryName, ErrorFlag] = gotodirectory(DirectoryName);
602            cd(DirStart);
603        end
604        [FileName, DirectoryName] = uiputfile('*.mat', 'Select a BPM Response File ("Save" starts measurement)', [DirectoryName FileName]);
605        drawnow;
606        if FileName == 0
607            ArchiveFlag = 0;
608            disp('   BPM response measurement canceled.');
609            Rmat = []; OutputFileName='';
610            return
611        end
612        FileName = [DirectoryName, FileName];
613    elseif FileName == -1
614        FileName = appendtimestamp(getfamilydata('Default', 'BPMRespFile'));
615        DirectoryName = getfamilydata('Directory', 'BPMResponse');
616        if isempty(DirectoryName)
617            DirectoryName = [getfamilydata('Directory','DataRoot'), 'Response', filesep, 'BPM', filesep];
618        end
619        FileName = [DirectoryName, FileName];
620    end
621   
622    % Acquire initial data
623    MachineConfig = getmachineconfig(InputFlags{:});
624end
625
626
627% Get the response matrices
628if strcmpi(ModeFlag,'Model')
629    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
630    % Model Response Matrix - Use LOCO Method %
631    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
632
633    % Just to make sure the proper AT model is the currrent model, do a get on one of the correctors
634    % (This is needed because locoresponsematrix does not check the .AT.ATModel field)
635    if isfamily(HCMFamily)
636        tmp = getsp(HCMFamily, HCMList, ModeFlag);
637    end
638
639
640    % % Mask bpms and correctors for status
641    % BPMxStatus = getfamilydata(BPMxFamily,'Status', BPMxList);
642    % BPMxGoodIndex = find(BPMxStatus);
643    % BPMxList = BPMxList(BPMxGoodIndex,:);
644    %
645    % BPMyStatus = getfamilydata(BPMyFamily,'Status', BPMyList);
646    % BPMyGoodIndex = find(BPMyStatus);
647    % BPMyList = BPMyList(BPMyGoodIndex,:);
648    %
649    % HCMStatus = getfamilydata(HCMFamily,'Status', HCMList);
650    % HCMGoodIndex = find(HCMStatus);
651    % HCMList = HCMList(HCMGoodIndex,:);
652    % HCMKicks = HCMKicks(HCMGoodIndex);
653    %
654    % VCMStatus = getfamilydata(VCMFamily,'Status', VCMList);
655    % VCMGoodIndex = find(VCMStatus);
656    % VCMList = VCMList(VCMGoodIndex,:);
657    % VCMKicks = VCMKicks(VCMGoodIndex);
658   
659    % Use AT (LOCO method)
660   
661    % 1. AT MODEL
662    global THERING
663    %setcavity off;
664    RINGData.Lattice = THERING;
665    iCavity = findcells(THERING, 'Frequency');
666    if isempty(iCavity)
667        if isstoragering
668            RINGData.CavityFrequency  = getrf('Model', 'Physics');
669            RINGData.CavityHarmNumber = getfamilydata('HarmonicNumber');
670        else
671            RINGData.CavityFrequency  = [];
672            RINGData.CavityHarmNumber = [];
673        end
674    else
675        RINGData.CavityFrequency  = THERING{iCavity(1)}.Frequency;
676        RINGData.CavityHarmNumber = THERING{iCavity(1)}.HarmNumber;
677    end
678   
679   
680    % 2. BPM STRUCTURE
681    % FamName and BPMIndex tells the findorbitrespm function which BPMs are needed in the response matrix
682    % HBPMIndex/VBPMIndex is the sub-index of BPMIndex which correspond to the measured response matrix
683    if strcmpi(BPMxFamily,'All')
684        BPMxATIndex = 1:length(THERING);
685    elseif isfamily(BPMxFamily)
686        BPMxATIndex = family2atindex(BPMxFamily, BPMxList);
687    else
688        BPMxATIndex = findcells(THERING, 'FamName', BPMxFamily);
689    end
690    if isempty(BPMxATIndex)
691        error(sprintf('BPMxFamily=%s could not be found in the AO or AT deck', BPMxFamily));
692    else
693        BPMxATIndex = BPMxATIndex(:)';    % Row vector
694    end
695   
696    if strcmpi(BPMyFamily,'All')
697        BPMyATIndex = 1:length(THERING);
698    elseif isfamily(BPMyFamily)
699        BPMyATIndex = family2atindex(BPMyFamily, BPMyList);
700    else
701        BPMyATIndex = findcells(THERING, 'FamName', BPMyFamily);
702    end
703    if isempty(BPMyATIndex)
704        error(sprintf('BPMyFamily=%s could not be found in the AO or AT deck', BPMyFamily));
705    else
706        BPMyATIndex = BPMyATIndex(:)';    % Row vector
707    end
708   
709    BPMData.BPMIndex = unique([BPMxATIndex BPMyATIndex]);
710    BPMData.HBPMIndex = findrowindex(BPMxATIndex', BPMData.BPMIndex');  % Only used after locoresponsematrix is called
711    BPMData.VBPMIndex = findrowindex(BPMyATIndex', BPMData.BPMIndex');  % Only used after locoresponsematrix is called
712       
713   
714    % 3. CORRECTOR MAGNET STRUCTURE
715    % FamName and HCMIndex/VCMIndex tells the findorbitrespm function which corrector magnets are in the response matrix
716    % CMData.HCMKicks = starting value for the horizontal kicks in milliradian
717    % CMData.VCMKicks = starting value for the vertical   kicks in milliradian
718    % CMData.HCMCoupling = starting value for the horizontal coupling (default: zeros)
719    % CMData.VCMCoupling = starting value for the vertical   coupling (default: zeros)
720    % Note:  The kick strength should match the measured response matrix as best as possible
721    % Note:  The kicks and Coupling are used all the time (fit or not!)
722   
723    % Note the different units between AT and LOCO
724    if strcmpi(HCMFamily,'All')
725        ATIndex = 1:length(THERING);
726    elseif isfamily(HCMFamily)
727        ATIndex = family2atindex(HCMFamily, HCMList);
728    else
729        ATIndex = findcells(THERING, 'FamName', HCMFamily);
730    end
731    if isempty(ATIndex)
732        error(sprintf('HCMFamily=%s could not be found in the middle layer or AT model', HCMFamily));
733    else
734        ATIndex = ATIndex(:)';    % Row vector
735    end
736    CMData.HCMIndex = ATIndex;
737   
738    if strcmpi(VCMFamily,'All')
739        ATIndex = 1:length(THERING);
740    elseif isfamily(VCMFamily)
741        ATIndex = family2atindex(VCMFamily, VCMList);
742    else
743        ATIndex = findcells(THERING, 'FamName', VCMFamily);
744    end
745    if isempty(ATIndex)
746        error(sprintf('VCMFamily=%s could not be found in the middle layer or AT model', VCMFamily));
747    else
748        ATIndex = ATIndex(:)';    % Row vector
749    end
750    CMData.VCMIndex = ATIndex;
751   
752    % Kicks must be in Physics units
753   
754    % Default kicks
755    if ismemberof(HCMFamily,'COR')
756        if isempty(HCMKicks)
757            HCMKicks = getfamilydata(HCMFamily, 'Setpoint', 'DeltaRespMat', HCMList);
758            if isempty(HCMKicks)
759                CMData.HCMKicks = Default2HCMKick;
760            else
761                %if strcmpi(getfamilydata(HCMFamily, 'Setpoint', 'Units'), 'Hardware')
762                    HCMsp = getsp(HCMFamily, HCMList, 'Numeric', ModeFlag, 'Hardware');
763                    CMData.HCMKicks = hw2physics(HCMFamily, 'Setpoint', HCMsp+HCMKicks, HCMList) - hw2physics(HCMFamily, 'Setpoint', HCMsp, HCMList);
764                %else
765                %    CMData.HCMKicks = HCMKicks;
766                %end
767            end
768        else
769            if strcmpi(UnitsFlag, 'Hardware')
770                % Change to AT units [radian]
771                HCMsp = getsp(HCMFamily, HCMList, 'Numeric', ModeFlag, 'Hardware');
772                CMData.HCMKicks = hw2physics(HCMFamily, 'Setpoint', HCMsp+HCMKicks, HCMList) - hw2physics(HCMFamily, 'Setpoint', HCMsp, HCMList);
773            else
774                CMData.HCMKicks = HCMKicks;
775            end
776        end
777    else
778        % Not a corrector magnet location
779        if isempty(HCMKicks)
780            CMData.HCMKicks = Default2HCMKick;
781        else
782            % The kick must be in physics units
783            if strcmpi(UnitsFlag, 'Hardware')
784                fprintf('\n   You are using a non-corrector magnet actuator type and using hardware units.\n');
785                fprintf('   Unknown conversion method from hardware to physics.\n\n');
786                fprintf('   Change to a physics units input scheme.\n');
787                error('Hardware to physics conversion error');
788            else
789                CMData.HCMKicks = HCMKicks;   
790            end
791        end
792    end
793   
794    if ismemberof(VCMFamily,'COR')
795        if isempty(VCMKicks)
796            VCMKicks = getfamilydata(VCMFamily, 'Setpoint', 'DeltaRespMat', VCMList);
797            if isempty(VCMKicks)
798                CMData.VCMKicks = Default2VCMKick;
799            else
800                %if strcmpi(getfamilydata(VCMFamily, 'Setpoint', 'Units'), 'Hardware')
801                    VCMsp = getsp(VCMFamily, VCMList, 'Numeric', ModeFlag, 'Hardware');
802                    CMData.VCMKicks = hw2physics(VCMFamily, 'Setpoint', VCMsp+VCMKicks, VCMList) - hw2physics(VCMFamily, 'Setpoint', VCMsp, VCMList);
803                %else
804                %    CMData.VCMKicks = VCMKicks;
805                %end
806            end
807        else
808            if strcmpi(UnitsFlag, 'Hardware')
809                % Change to AT units [radian]
810                VCMsp = getsp(VCMFamily, VCMList, 'Numeric', ModeFlag, 'Hardware');
811                CMData.VCMKicks = hw2physics(VCMFamily, 'Setpoint', VCMsp+VCMKicks, VCMList) - hw2physics(VCMFamily, 'Setpoint', VCMsp, VCMList);
812            else
813                CMData.VCMKicks = VCMKicks;
814            end
815        end
816    else
817        % Not a corrector magnet location
818        if isempty(VCMKicks)
819            CMData.VCMKicks = Default2VCMKick;
820        else
821            % The kick must be in physics units
822            if strcmpi(UnitsFlag, 'Hardware')
823                fprintf('\n   You are using a non-corrector magnet actuator type and using hardware units.\n');
824                fprintf('   Unknown conversion method from hardware to physics!\n\n');
825                fprintf('   Change to a physics units input scheme.\n');
826                error('Hardware to physics conversion error');
827            else
828                CMData.VCMKicks = VCMKicks;   
829            end
830        end
831    end
832   
833    CMData.HCMKicks = CMData.HCMKicks(:);
834    if length(CMData.HCMKicks) == 1
835        CMData.HCMKicks = CMData.HCMKicks * ones(length(CMData.HCMIndex),1);
836    end
837    CMData.VCMKicks = CMData.VCMKicks(:);
838    if length(CMData.VCMKicks) == 1
839        CMData.VCMKicks = CMData.VCMKicks * ones(length(CMData.VCMIndex),1);
840    end
841   
842    % Corrector gain error have been taken into account by hw2physics
843    % If the model has corrector rolls, adjust the kicks now.
844   
845    for i = 1:length(CMData.HCMIndex)
846        if isfield(THERING{CMData.HCMIndex(i)}, 'Roll')           
847            Roll = THERING{CMData.HCMIndex(i)}.Roll;
848        else
849            Roll = [0 0];  % [Rollx Rolly]
850        end
851        HCMRoll(i,1) = Roll(1);
852    end
853    %HCMRoll = getroll(HCMFamily, HCMList);
854   
855    for i = 1:length(CMData.VCMIndex)
856        if isfield(THERING{CMData.VCMIndex(i)}, 'Roll')           
857            Roll = THERING{CMData.VCMIndex(i)}.Roll;
858        else
859            Roll = [0 0];  % [Rollx Rolly]
860        end
861        VCMRoll(i,1) = Roll(2);
862    end
863    %VCMRoll = getroll(VCMFamily, VCMList);
864
865    % The kicks need to be adjusted for roll (model coordinates)
866    HCMKicks = CMData.HCMKicks;
867    VCMKicks = CMData.VCMKicks;
868    CMData.HCMKicks = CMData.HCMKicks .* cos(HCMRoll);
869    CMData.VCMKicks = CMData.VCMKicks .* cos(VCMRoll);
870   
871   
872    % Coupling term (convert from ML to LOCO coordinates)
873    % The ./cos term is needed because LOCO coupling is scaling the unrolled kick
874    CMData.HCMCoupling =  sin(HCMRoll) ./ cos(HCMRoll);
875    CMData.VCMCoupling = -sin(VCMRoll) ./ cos(VCMRoll);
876   
877
878    % Generate a response matrix ('FixedPathLength' or 'FixedMomentum', 'Linear' or 'Full')
879    % Flags is empty then the locoresponsematrix defaults are used (which was fix path length, linear the last time I checked)
880    R0 = locoresponsematrix(RINGData, BPMData, CMData, LOCORespFlags);
881
882   
883    % Coupling correction   
884    % Convert the ML gain/rolls to LOCO gain/coupling
885    % for i = 1:length(BPMData.BPMIndex)
886    %     if isfield(THERING{BPMData.BPMIndex(i)}, 'GCR')           
887    %         GCR = THERING{BPMData.BPMIndex(i)}.GCR;
888    %     else
889    %         GCR = [1 1 0 0];  % [Gx Gy Crunch Roll]
890    %     end
891    %     
892    %     M = gcr2loco(GCR(1), GCR(2), GCR(3), GCR(4));
893    %     BPMxGainLOCO(i,1)     = M(1,1);
894    %     BPMxCouplingLOCO(i,1) = M(1,2);
895    %     BPMyGainLOCO(i,1)     = M(2,2);
896    %     BPMyCouplingLOCO(i,1) = M(2,1);
897    % end
898    %
899    %
900    % % Build a rotation matrix
901    % C = [diag(BPMxGainLOCO)      diag(BPMxCouplingLOCO)
902    %      diag(BPMyCouplingLOCO)  diag(BPMyGainLOCO)];
903
904   
905    % BPM coupling correction (only roll, crunch correction, gain is done in physics2hw (via real2raw))   
906    % Still in physics units, just rotate and crunch.
907    NBPM = length(BPMData.BPMIndex);
908    for i = 1:NBPM
909        if isfield(THERING{BPMData.BPMIndex(i)}, 'GCR')           
910            GCR = THERING{BPMData.BPMIndex(i)}.GCR;
911        else
912            GCR = [1 1 0 0];  % [Gx Gy Crunch Roll]
913        end
914        %Gx = GCR(1);  % Not used
915        %Gy = GCR(2);  % Not used
916        Crunch = GCR(3);
917        Roll = GCR(4);
918       
919        a(i,1) = ( Crunch * sin(Roll) + cos(Roll)) / sqrt(1 - Crunch^2);
920        b(i,1) = (-Crunch * cos(Roll) + sin(Roll)) / sqrt(1 - Crunch^2);
921        c(i,1) = (-Crunch * cos(Roll) - sin(Roll)) / sqrt(1 - Crunch^2);
922        d(i,1) = (-Crunch * sin(Roll) + cos(Roll)) / sqrt(1 - Crunch^2);
923
924        % Same as:
925        %%m = gcr2loco(GCR(1), GCR(2), GCR(3), GCR(4));
926        %m = gcr2loco(1, 1, GCR(3), GCR(4));
927        %a(i,1)= m(1,1);
928        %b(i,1)= m(1,2);
929        %c(i,1)= m(2,1);
930        %d(i,1)= m(2,2);
931    end
932 
933    % Build a rotation matrix
934    C = [diag(a)  diag(b)
935         diag(c)  diag(d)];
936
937    % Rotate & crunch the AT model response matrix
938    R0 = C * R0;
939   
940
941    % Split up R0 into an array
942    Rmat(1,1).Data = R0(                         BPMData.HBPMIndex , 1:length(CMData.HCMIndex));
943    Rmat(2,1).Data = R0(length(BPMData.BPMIndex)+BPMData.VBPMIndex , 1:length(CMData.HCMIndex));
944    Rmat(1,2).Data = R0(                         BPMData.HBPMIndex , length(CMData.HCMIndex)+(1:length(CMData.VCMIndex)));
945    Rmat(2,2).Data = R0(length(BPMData.BPMIndex)+BPMData.VBPMIndex , length(CMData.HCMIndex)+(1:length(CMData.VCMIndex)));
946   
947   
948    % Convert to meters/radian (don't use the rolled kick strength)
949    for i = 1:length(CMData.HCMKicks)
950        Rmat(1,1).Data(:,i) = Rmat(1,1).Data(:,i) / HCMKicks(i);
951        Rmat(2,1).Data(:,i) = Rmat(2,1).Data(:,i) / HCMKicks(i);
952    end
953   
954    for i = 1:length(CMData.VCMKicks)
955        Rmat(1,2).Data(:,i) = Rmat(1,2).Data(:,i) / VCMKicks(i);
956        Rmat(2,2).Data(:,i) = Rmat(2,2).Data(:,i) / VCMKicks(i);
957    end
958   
959   
960    % Build the rest of the response matrix structure in 'Physics' units
961   
962    if ismemberof(BPMxFamily,'BPM') && ismemberof(BPMyFamily,'BPM')
963        % getpvmodel is better because crunch and roll are included
964        Xat = getam(BPMxFamily, BPMxList, 'Physics', ModeFlag);
965        Yat = getam(BPMyFamily, BPMyList, 'Physics', ModeFlag);
966    else
967        % The orbit does not have to be at the BPMs so use modeltwiss 
968        [Xat, Yat, Sx, Sy] = modeltwiss('ClosedOrbit', BPMxFamily, BPMxList, BPMyFamily, BPMyList);
969    end
970    X.Data = Xat(:);
971    Y.Data = Yat(:);
972    X.FamilyName = BPMxFamily;
973    Y.FamilyName = BPMyFamily;
974    X.Field = 'Monitor';
975    Y.Field = 'Monitor';
976    X.DeviceList = BPMxList;
977    Y.DeviceList = BPMyList;
978    X.Status = ones(length(Xat),1);
979    Y.Status = ones(length(Yat),1);
980    X.Mode = 'Model';
981    Y.Mode = 'Model';
982    X.t = 0;
983    Y.t = 0;
984    X.tout = 0;
985    Y.tout = 0;
986    X.TimeStamp = clock;
987    Y.TimeStamp = X.TimeStamp;
988    X.Units = 'Physics';
989    Y.Units = 'Physics';
990    X.UnitsString = 'm';
991    Y.UnitsString = 'm';
992    X.DataDescriptor = 'Horizontal Orbit';
993    Y.DataDescriptor = 'Vertical Orbit';
994    X.CreatedBy = 'getpv';
995    Y.CreatedBy = 'getpv';
996   
997    HCMsp = getsp(HCMFamily, HCMList, 'Struct', ModeFlag, 'Physics');
998    VCMsp = getsp(VCMFamily, VCMList, 'Struct', ModeFlag, 'Physics');
999    Rmat(1,1).Monitor = X;
1000    Rmat(1,1).Actuator = HCMsp;
1001    Rmat(1,2).Monitor = X;
1002    Rmat(1,2).Actuator = VCMsp;
1003    Rmat(2,1).Monitor = Y;
1004    Rmat(2,1).Actuator = HCMsp;
1005    Rmat(2,2).Monitor = Y;
1006    Rmat(2,2).Actuator = VCMsp;
1007   
1008    Rmat(1,1).ActuatorDelta = HCMKicks;  %CMData.HCMKicks;
1009    Rmat(2,1).ActuatorDelta = HCMKicks;  %CMData.HCMKicks;
1010    Rmat(1,2).ActuatorDelta = VCMKicks;  %CMData.VCMKicks;
1011    Rmat(2,2).ActuatorDelta = VCMKicks;  %CMData.VCMKicks;
1012   
1013    for i = 1:2
1014        for j = 1:2
1015            Rmat(i,j).GeV = getenergymodel;
1016            Rmat(i,j).TimeStamp = X.TimeStamp;
1017            Rmat(i,j).DCCT = [];
1018            Rmat(i,j).ModulationMethod = ModulationMethod;
1019            Rmat(i,j).WaitFlag = WaitFlag;
1020            Rmat(i,j).ExtraDelay = ExtraDelay;
1021            Rmat(i,j).Units = 'Physics';
1022            Rmat(i,j).UnitsString = [Rmat(1,1).Monitor.UnitsString, '/', Rmat(1,1).Actuator.UnitsString];
1023            Rmat(i,j).DataDescriptor = 'Response Matrix';
1024            Rmat(i,j).CreatedBy = 'measbpmresp';
1025            Rmat(i,j).OperationalMode = getfamilydata('OperationalMode');
1026        end
1027    end
1028           
1029    if strcmpi(UnitsFlag, 'Hardware')
1030        % Change to hardware units [mm/amp]
1031        if ismemberof(BPMxFamily,'BPM') && ismemberof(BPMyFamily,'BPM') && ismemberof(HCMFamily,'COR') && ismemberof(VCMFamily,'COR')
1032            Rmat = physics2hw(Rmat, getenergymodel);
1033        else
1034            fprintf('\n   You are asking for hardware units, but a nonstandard monitor and/or\n');
1035            fprintf('   actuator was used.  The response matrix will stay in physics units!\n\n');
1036        end
1037    end
1038
1039else
1040
1041    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1042    % Online or Simulated Response Matrix %
1043    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1044    % Online or Simulated response matrix
1045
1046    Message = ['Your are about to measure an orbit response matrix\n' ...
1047        'Please check the following steps have been performed before starting\n\n' ...
1048        'Do not forget to switch OFF QT magnets before any measurement', ...
1049        '1. All feedbacks are OFF \n' ...
1050        '2. Tune excitations are OFF \n' ...
1051        '3. Booster tuned to economic mode \n' ...
1052        '4. Dispersion function has been measured and archived \n' ...
1053        '5. BPM noise has been measured and looks fine \n\n' ...
1054        'Do you want to continue?\n'];
1055    button = questdlg(sprintf(Message),'Orbit response Matrix Measurement','Cancel');
1056
1057    if ~strcmp(button,'Yes')
1058        fprintf('Orbit measurement canceled \n');
1059        return;
1060    end
1061
1062
1063    % Default kicks
1064    if isempty(HCMKicks)
1065        HCMKicks = getfamilydata(HCMFamily, 'Setpoint', 'DeltaRespMat', HCMList);
1066        KickUnits = 'Hardware'; %getfamilydata(HCMFamily, 'Setpoint', 'Units');
1067        if isempty(HCMKicks)
1068            HCMKicks = Default2HCMKick;
1069            KickUnits = 'Physics';
1070        end
1071        if isempty(KickUnits)
1072            error('Units for the kick strength are unknown.  Try inputing units directly.');
1073        end
1074        if strcmpi(UnitsFlag, 'Physics') && strcmpi(KickUnits, 'Hardware')
1075            HCMsp = getsp(HCMFamily, HCMList, 'Numeric', ModeFlag, 'Hardware');
1076            HCMKicks = hw2physics(HCMFamily, 'Setpoint', HCMsp+HCMKicks, HCMList) - hw2physics(HCMFamily, 'Setpoint', HCMsp, HCMList);
1077        elseif strcmpi(UnitsFlag, 'Hardware') && strcmpi(KickUnits, 'Physics')
1078            HCMsp = getsp(HCMFamily, HCMList, 'Numeric', ModeFlag, 'Physics');
1079            HCMKicks = physics2hw(HCMFamily, 'Setpoint', HCMsp+HCMKicks, HCMList) - physics2hw(HCMFamily, 'Setpoint', HCMsp, HCMList);
1080        end
1081    end
1082    if isempty(VCMKicks)
1083        VCMKicks = getfamilydata(VCMFamily, 'Setpoint', 'DeltaRespMat', VCMList);
1084        KickUnits = 'Hardware'; %getfamilydata(VCMFamily, 'Setpoint', 'Units');
1085        if isempty(VCMKicks)
1086            VCMKicks = Default2VCMKick;
1087            KickUnits = 'Physics';
1088        end
1089        if isempty(KickUnits)
1090            error('Units for the kick strength are unknown.  Try inputing units directly.');
1091        end
1092        if strcmpi(UnitsFlag, 'Physics') && strcmpi(KickUnits, 'Hardware')
1093            VCMsp = getsp(VCMFamily, VCMList, 'Numeric', ModeFlag, 'Hardware');
1094            VCMKicks = hw2physics(VCMFamily, 'Setpoint', VCMsp+VCMKicks, VCMList) - hw2physics(VCMFamily, 'Setpoint', VCMsp, VCMList);
1095        elseif strcmpi(UnitsFlag, 'Hardware') && strcmpi(KickUnits, 'Physics')
1096            VCMsp = getsp(VCMFamily, VCMList, 'Numeric', ModeFlag, 'Physics');
1097            VCMKicks = physics2hw(VCMFamily, 'Setpoint', VCMsp+VCMKicks, VCMList) - physics2hw(VCMFamily, 'Setpoint', VCMsp, VCMList);
1098        end
1099    end
1100   
1101    %% Query to begin measurement
1102    %if DisplayFlag
1103    %    tmp = questdlg('Begin response matrix measurement?','Response Matrix Measurement','Yes','No','No');
1104    %    if strcmpi(tmp,'No')
1105    %        fprintf('   Response matrix measurement aborted\n');
1106    %        Rmat = [];
1107    %        return
1108    %    end
1109    %end
1110   
1111    % Mask bpms and correctors for status
1112    BPMxStatus = getfamilydata(BPMxFamily,'Status', BPMxList);
1113    BPMxGoodIndex = find(BPMxStatus);
1114    BPMxList = BPMxList(BPMxGoodIndex,:);
1115   
1116    BPMyStatus = getfamilydata(BPMyFamily,'Status', BPMyList);
1117    BPMyGoodIndex = find(BPMyStatus);
1118    BPMyList = BPMyList(BPMyGoodIndex,:);
1119   
1120    HCMStatus = getfamilydata(HCMFamily,'Status', HCMList);
1121    HCMGoodIndex = find(HCMStatus);
1122    HCMList = HCMList(HCMGoodIndex,:);
1123    if length(HCMKicks) == 1
1124        HCMKicks = HCMKicks * ones(length(HCMGoodIndex),1);
1125    else
1126        HCMKicks = HCMKicks(HCMGoodIndex);
1127    end
1128
1129    VCMStatus = getfamilydata(VCMFamily,'Status', VCMList);
1130    VCMGoodIndex = find(VCMStatus);
1131    VCMList = VCMList(VCMGoodIndex,:);
1132    if length(VCMKicks) == 1
1133        VCMKicks = VCMKicks * ones(length(VCMGoodIndex),1);
1134    else
1135        VCMKicks = VCMKicks(VCMGoodIndex);
1136    end
1137   
1138    % Measure response matrix of all planes at once
1139    % (One advantage of this is the limits of all planes get checked before the measurement starts)
1140    if DisplayFlag
1141        fprintf('   Begin BPM response matrix measurement\n');
1142    end
1143   
1144    %if strcmpi(getfamilydata('Machine'), 'ALS')
1145    %    fprintf('   Using measrespmat_als (with orbit correction)\n');
1146    %    Rcell = measrespmat_als({BPMxFamily,BPMyFamily}, {BPMxList,BPMyList}, {HCMFamily,VCMFamily}, {HCMList,VCMList}, {HCMKicks,VCMKicks}, 'Struct', ModulationMethod, WaitFlag, ExtraDelay, InputFlags{:}, DCCTFlag{:});
1147    %else
1148        Rcell = measrespmat({BPMxFamily,BPMyFamily}, {BPMxList,BPMyList}, {HCMFamily,VCMFamily}, {HCMList,VCMList}, {HCMKicks,VCMKicks}, 'Struct', ModulationMethod, WaitFlag, ExtraDelay, InputFlags{:}, DCCTFlag{:});
1149    %end
1150    if DisplayFlag
1151        fprintf('   Measurement complete.\n\n');
1152    end
1153
1154    % Convert cell array to a struct array
1155    % (We only did this because struct arrays were more familiar to people)
1156    % Rmat(1,1) = Rcell{1,1};  % Kick x, look x
1157    % Rmat(2,1) = Rcell{2,1};  % Kick x, look y
1158    % Rmat(2,2) = Rcell{2,2};  % Kick y, look y
1159    % Rmat(1,2) = Rcell{1,2};  % Kick y, look x
1160    for i = 1:size(Rcell,1)
1161        for j = 1:size(Rcell,2)
1162            if istransport
1163                % For transport line zero the BPM noise for upstream BPMs
1164                for k = 1:size(Rcell{i,j}.Data,2)
1165                    CMpos = getspos(Rcell{i,j}.Actuator.FamilyName, Rcell{i,j}.Actuator.DeviceList(k,:));
1166                    BPMpos = getspos(Rcell{i,j}.Monitor);
1167                    iUpStream = find(BPMpos < CMpos);
1168                    if ~isempty(iUpStream)
1169                        Rcell{i,j}.Data(iUpStream,k) = 0;
1170                    end
1171                end
1172            end
1173            Rmat(i,j) = Rcell{i,j};
1174        end
1175    end
1176   
1177   
1178    % % Horizontal corrector plane
1179    % if DisplayFlag
1180    %     fprintf('   Begin Horizontal plane measurement ...\n');
1181    % end
1182    % mat = measrespmat('Struct', {BPMxFamily, BPMyFamily}, {BPMxList, BPMyList}, HCMFamily, HCMList, HCMKicks, ModulationMethod, WaitFlag, ExtraDelay, InputFlags{:});
1183    % if DisplayFlag
1184    %     fprintf('   Horizontal plane complete.\n\n');
1185    % end   
1186    %
1187    % % Make a response matrix array
1188    % Rmat(1,1) = mat{1};  % Kick x, look x
1189    % Rmat(2,1) = mat{2};  % Kick x, look y
1190    %
1191    %
1192    % % Vertical corrector plane
1193    % if DisplayFlag
1194    %     fprintf('   Begin Vertical plane measurement...\n');
1195    % end
1196    % mat = measrespmat('Struct', {BPMxFamily, BPMyFamily}, {BPMxList, BPMyList}, VCMFamily, VCMList, VCMKicks, ModulationMethod, WaitFlag, ExtraDelay, InputFlags{:});
1197    % if DisplayFlag
1198    %     fprintf('   Vertical plane complete.\n\n');     
1199    % end
1200    %
1201    % Rmat(2,2) = mat{2};  % Kick y, look y
1202    % Rmat(1,2) = mat{1};  % Kick y, look x
1203end
1204
1205% Save data in the proper directory
1206if ArchiveFlag || ischar(FileName)
1207    [DirectoryName, FileName, Ext] = fileparts(FileName);
1208    DirStart = pwd;
1209    [DirectoryName, ErrorFlag] = gotodirectory(DirectoryName);
1210    if ErrorFlag
1211        fprintf('\n   There was a problem getting to the proper directory!\n\n');
1212    end
1213    save(FileName, 'Rmat','MachineConfig');
1214    cd(DirStart);
1215    OutputFileName = [DirectoryName, FileName, '.mat'];
1216   
1217%     if DisplayFlag
1218        fprintf('   BPM response matrix data structure ''Rmat'' saved to disk\n');
1219        fprintf('   Filename: %s\n', OutputFileName);
1220        fprintf('   The total response matrix measurement time was %.2f minutes.\n', (gettime-TimeStart)/60);
1221%     end
1222else
1223    OutputFileName = '';
1224end
1225
1226
1227if ~StructOutputFlag
1228    % Return a matrix
1229    % Rmat = [Rmat(1,1).Data Rmat(1,2).Data;
1230    %         Rmat(2,1).Data Rmat(2,2).Data];
1231    RmatData = [];
1232    for i = 1:size(Rmat,1)
1233        Rrow = [];
1234        for j = 1:size(Rmat,2)
1235            Rrow = [Rrow Rmat(i,j).Data];
1236        end
1237        RmatData = [RmatData; Rrow];
1238    end
1239   
1240    Rmat = RmatData;
1241end
Note: See TracBrowser for help on using the repository browser.