source: MML/trunk/mml/setorbit.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: 60.5 KB
Line 
1function [OCS, OCS0, V, S, ErrorFlag] = setorbit(varargin)
2%SETORBIT - Orbit correction function
3%  Family/DeviceList method:
4%  [CM, OCS0, V, Svalues] = setorbit(GoalOrbit, BPMFamily, BPMDevList, CMFamily, CMDevList, NIter, SVDIndex, BPMWeight);
5%
6%  Data structure method:
7%  [CM, OCS0, V, Svalues] = setorbit(GoalOrbit, BPMstruct,             CMstruct,            NIter, SVDIndex, BPMWeight);
8%
9%  Use cell arrays for multiple family correction (like coupled planes):
10%  [CM, OCS0, V, Svalues] = setorbit(GoalOrbitCell, BPMcell, CMcell, NIter, SVDIndex, BPMWeight);
11%  Note: BPMcell and CMcell must be a data structures when using cell arrays (GoalOrbitCell can be a cell or a string)
12%
13%  Orbit Correction Structure (OCS) method:
14%  [CM, OCS0, V, Svalues] = setorbit(OCS, NIter, SVDIndex, BPMWeight);
15%
16%  INPUTS
17%  1. GoalOrbit - Goal orbit (vector or cell array)
18%                'Golden' for the golden orbit {Default}
19%                'Offset' for the offset orbit
20%  2. BPM - BPM data structure (or cell array of structures)
21%     or BPMFamily and BPMDevList
22%  3. CM - Corrector magnet data structure (or cell array of structures)
23%     or CMFamily and CMDevList
24%  4. SVDIndex - vector, maximum number, 'All', or
25%                base on a threshold of min/max singular value {Default: 1e-3}
26%  5. NIter - Number of iterations  {Default: 1}
27%            (NIter can be 0, see note 1 below)
28%  6. BPMWeight - Weight applied to the BPMs (OCS.BPMWeight)
29%  7. FLAGS  - 'Abs' or 'Inc' - GoalOrbit is an absolute or incremental change {Default: 'Abs'}
30%                               ('Absolute' or 'Incremental' can also be used)
31%              'CorrectorGain', Gain - Scale the correction by Gain {Default: 1}
32%              'Display' - plot orbit information before applying the correction
33%              'FigureHandles' followed by a vector of 1 or 2 elements for figure handles and
34%                                                      4 or 8 elements for axes handles.
35%              'FitRF' or 'SetRF' - Fit and change the RF frequency
36%                   'GoldenDisp' - Use the golden dispersion {Default}
37%                   'MeasDisp'   - Measure the dispersion
38%                   'ModelDisp'  - Calculate the model dispersion
39%              'GetPV' or 'NoGetPV' - Get new data or use the data already in the OCS {Default: 'GetPV' (for the first iteration)}
40%                                     This allows one make a correction based on data already checked and analyzed.
41%                                     ('GetAM' or 'NoGetAM' does the same thing)
42%              'GoldenResp' or 'ModelResp' - Golden BPM response or calculate from the model {Default: 'GoldenResp'}
43%              'SetPV' or 'NoSetPV' - Set or don't set the correctors and RF {Default: 'SetSP'}
44%                                    'NoSetPV' does the calculation without making the correction.  That way one can
45%                                     take a look at the expected correction results before applying them.
46%                                     ('SetSP' or 'NoSetSP' does the same thing)
47%              'Tolerance', Tol - Quit correction if the std(error) < Tol {Tol: 0}
48%              'RampSteps', NSteps - Number of steps to ramp in the correction {NSteps: 1}
49%                                    This is used to avoid a large transient between setpoint changes.
50%                                    Note: NSteps is only used on the first iteration.
51%              'FitRF','SetRF','RFCorrector'                       - Set the RF frequency (Eta Column)
52%              'FitRFHCM0','FitRFEnergy','SetRFHCM0','SetRFEnergy' - Set the RF frequency (HCM energy constraint)
53%              'FitRFDeltaHCM0','SetRFDeltaHCM0'                   - Set the RF frequency (Delta HCM energy constraint)
54%              'FitRFDispersionOrbit','SetRFDispersionOrbit'       - Set the RF frequency (Dispersion orbit constraint)
55%              'FitRFDispersionHCM','SetRFDispersionHCM'           - Set the RF frequency (Dispersion correction constraint)
56%              The usual Units and Mode flags can also be used.
57%              Flags are not case sensitive
58%
59%  OUTPUTS
60%  1. OCS    - New orbit correction structure (OCS)
61%  2. OCS0   - Starting OCS
62%  3. V      - Corrector magnet singular vectors
63%  4. Svalue - Singular values (vector)
64%
65%  ALGORITHM
66%  SVD orbit correction:
67%  Decompose the response matrix, Rmat:
68%    [U, S, V] = svd(Rmat);
69%
70%  The V matrix columns are the singular vectors in the corrector magnet space
71%  The U matrix columns are the singular vectors in the BPM space
72%    Rmat = U * S = Rmat * V
73%
74%  Modify the response matrix by removing singular vector with small singular values
75%    Rmod = U(:,SVDIndex) * S(SVDIndex,SVDIndex) = Rmat * V(:,SVDIndex)
76%
77%  Only project (least squares) on to the modified response matrix
78%    b = inv(Rmod'*Rmod)*Rmod' * (GoalOrbit - PresentOrbit);
79%  Or
80%    b = Rmod \ (GoalOrbit - PresentOrbit);
81%
82%  The b coefficients are in terms of the singular vectors.
83%  The corrector strengths come from the linear combination of the singular vectors
84%    DeltaCM = V(:,SVDIndex) * b;
85%
86%  ORBIT CORRECTION STRUCTURE (OCS)
87%    OCS.BPM (Data structure or cell array of data structures)
88%    OCS.CM  (Data structure or cell array of data structures)
89%    OCS.GoalOrbit
90%    OCS.NIter         - Number of correction iterations
91%    OCS.NCorrections  - Number of corrections actually done
92%    OCS.Tolerance     - Tolerance level to quit iterating
93%    OCS.RampSteps     - Number of steps to ramp in the each correction
94%    OCS.SVDIndex
95%    OCS.FitRF         - Methods for RF correction
96%                        1 Standard way with no constraints
97%                        2 Sum of the energy change to zero Also remove the
98%                          energy change due to the present corrector setpoints
99%                        3 Sum of the energy change to zero
100%                          remove energy change due to the incremental change in the correctors
101%                        4 Constraint: dot(DispersionX,   Smat * dHCM) = 0
102%                        5 Constraint: dot(HCM(Dispersion), dHCM) = 0
103%    OCS.RF
104%    OCS.DeltaRF
105%    OCS.Display
106%    OCS.Incremental   - GoalOrbit is an incremental change from the present (1) or absolute (0) {Default: 0}
107%    OCS.CorrectorGain - Scales the correction (usually used in slow feedback)
108%    OCS.BPMWeight     - Row    weights on the response matrix
109%    OCS.CMWeight      - Column weights on the response matrix
110%    OCS.Flags = {}
111%
112%  EXAMPLES
113%  1. The default behavior us horizontal and vertical (coupled) orbit correction to the golden orbit
114%     setorbit;
115%     is equivalent to
116%     x = getx('struct');
117%     y = gety('struct');
118%     hcm = getsp('HCM','struct');
119%     vcm = getsp('VCM','struct');
120%     setorbit('Golden', {x,y}, {hcm,vcm});
121%
122%  2. Horizontal orbit correction with the follow criterion:
123%     a. Correct the horizontal plane to the golden orbit
124%     b. 3 Iterations
125%     c. Use the first 10 singular values
126%     d. Display results
127%
128%     x = getx([1 1;1 2;12 1; 13 4],'struct');
129%     hcm = getsp('HCM',[3 1;5 1;10 1],'struct');
130%     setorbit('Golden', x, hcm, 3, 10, 'Display');
131%
132%  3. Horizontal and vertical (coupled) orbit correction to the golden orbit (display results)
133%     x = getx([1 1;1 2;12 1; 13 4],'struct');
134%     y = gety([1 1;1 2;12 1; 13 4],'struct');
135%     hcm = getsp('HCM',[3 1;5 1;10 1],'struct');
136%     vcm = getsp('VCM',[3 1;4 1;9 1;10 1],'struct');
137%     setorbit('Golden', {x,y}, {hcm,vcm}, 'Display');
138%
139%  NOTES
140%  1. Incremental orbit changes with more then one iteration are treated algorithmically
141%     just like absolute orbit changes.  For a 1 iteration incremental orbit change
142%     BPM data is not needed and hence not used.  However, if one uses the
143%     'Display' flag then BPM data is used to show results.  If BPM data is not
144%     available and one wants to still display corrector and estimated orbit
145%     information then use the special mode: 'Inc', 'Display', NIter=0.
146%  2. The 'Display' flag only displays the first iteration and the final result.
147%     Intermediate iterations (if used) are not displayed.
148%  3. If horizontal and vertical corrector are used, then the
149%     coupling terms in the response matrix will be used.
150%     To avoid using coupling terms, use separate calls.
151%  4. OCS0.CM.Data is the corrector strength before setorbit ran
152%     OCS.CM.Data  is the corrector strength after  setorbit ran
153%     Hence, DeltaCM = OCS.CM.Data - OCS0.CM.Data;
154%     However, if the 'NoSetSP' flag was used, then no correction was done and
155%     OCS.CM.Data=OCS0.CM.Data (ie, the present corrector strength).  To apply
156%     the correction, use OCS.CM.Data + OCS.CM.Delta
157%
158%  See also orbitcorrectionmethods, setorbitbump, setorbitgui, rmdisp, plotcm
159
160%  Written by Greg Portmann
161%  Modified by Laurent S. Nadolski
162%  23 September, 2008 OCS.FitRFtest added by Laurent S. Nadolski
163%  Has to work even if masterclock is off
164
165
166% Initialize
167ErrorFlag = 0;
168ExtraDelay = 0;
169DCCTLOW = .1;    % A minimum stored current into the machine
170
171DefaultNIter = 1;
172DefaultSVDIndex = 1e-4;
173DefaultGoalOrbit = 'Golden';
174DefaultFitRF = 0;
175DefaultDisplay = 0;
176DefaultCorrectorGain = 1;
177
178RespFlag = 'GoldenResp';
179DispFlag = 'GoldenDisp';
180SetSPFlag = 1;
181GetPVFlag = 1;
182RF0 = [];
183RF  = [];
184FigHandles = [];
185AxesHandles = [];
186
187%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
188% Input parsing and checking %
189%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
190IncrementalFlag = -1;
191ModeFlag = '';
192InputFlags = {};
193OCSFlags = {};
194
195% OCS init and defaults
196OCS.BPM = [];
197OCS.CM  = [];
198OCS.GoalOrbit = DefaultGoalOrbit;
199OCS.SVDIndex  = DefaultSVDIndex;
200OCS.FitRF     = DefaultFitRF;
201OCS.NIter     = DefaultNIter;
202OCS.Display   = DefaultDisplay;
203OCS.CorrectorGain = DefaultCorrectorGain;
204OCS.Incremental = 0;
205OCS.Tolerance = 0;
206OCS.RampSteps = 1;
207
208% First check if an OCS structure was input
209OCSInputFlag = 0;
210if length(varargin) >= 1
211    if isstruct(varargin{1})
212        if isfield(varargin{1},'BPM') && isfield(varargin{1},'CM')
213            OCSInputFlag = 1;
214                       
215            OCSin = varargin{1};
216            varargin(1) = [];
217
218            % Copy the input OSC on top of the defaults
219            FieldCell = fieldnames(OCSin);
220            for i = 1:length(FieldCell)
221                OCS.(FieldCell{i}) = OCSin.(FieldCell{i});
222            end
223           
224            % Attach the flags
225            if isfield(OCS, 'Flags')
226                varargin = [varargin OCS.Flags];
227            end
228        end
229    end
230end
231
232
233for i = length(varargin):-1:1
234    if isstruct(varargin{i})
235        % Ignor structures
236    elseif iscell(varargin{i})
237        % Ignor cells
238
239    elseif strcmpi(varargin{i},'Golden')
240        % Use the golden orbit
241        OCS.GoalOrbit = 'Golden';
242        varargin(i) = [];
243    elseif strcmpi(varargin{i},'Offset')
244        % Use the offset orbit
245        OCS.GoalOrbit = 'Offset';
246        varargin(i) = [];
247
248    elseif any(strcmpi(varargin{i},{'FitRF','SetRF','RFCorrector'}))
249        %SetRFString = 'Set the RF frequency (Eta Column)';
250        OCS.FitRF = 1;
251        varargin(i) = [];
252    elseif any(strcmpi(varargin{i},{'FitRFHCM0','FitRFEnergy','SetRFHCM0','SetRFEnergy'}))
253        %SetRFString = 'Set the RF frequency (HCM energy constraint)';
254        OCS.FitRF = 2;
255        varargin(i) = [];
256    elseif any(strcmpi(varargin{i},{'FitRFDeltaHCM0','SetRFDeltaHCM0'}))
257        %SetRFString = 'Set the RF frequency (Delta HCM energy constraint)';
258        OCS.FitRF = 3;
259        varargin(i) = [];
260    elseif any(strcmpi(varargin{i},{'FitRFDispersionOrbit','SetRFDispersionOrbit'}))
261        %SetRFString = 'Set the RF frequency (Dispersion orbit constraint)';
262        OCS.FitRF = 4;
263        varargin(i) = [];
264    elseif any(strcmpi(varargin{i},{'FitRFDispersionHCM','SetRFDispersionHCM'}))
265        %SetRFString = 'Set the RF frequency (Dispersion correction constraint)';
266        OCS.FitRF = 5;
267        varargin(i) = [];
268
269    elseif strcmpi(varargin{i},'Display')
270        OCS.Display = 1;
271        varargin(i) = [];
272    elseif strcmpi(varargin{i},'NoDisplay') || strcmpi(varargin{i},'No Display')
273        OCS.Display = 0;
274        varargin(i) = [];
275
276    elseif strcmpi(varargin{i},'ModelResp')
277        RespFlag = varargin{i};
278        varargin(i) = [];
279    elseif strcmpi(varargin{i},'GoldenResp')
280        RespFlag = varargin{i};
281        varargin(i) = [];
282
283    elseif strcmpi(varargin{i},'ModelDisp')
284        DispFlag = varargin{i};
285        varargin(i) = [];
286    elseif strcmpi(varargin{i},'MeasDisp')
287        DispFlag = varargin{i};
288        varargin(i) = [];
289    elseif strcmpi(varargin{i},'GoldenDisp')
290        DispFlag = varargin{i};
291        varargin(i) = [];
292
293    elseif any(strcmpi(varargin{i},{'Inc','Incremental'}))
294        OCS.Incremental = 1;
295        varargin(i) = [];
296    elseif any(strcmpi(varargin{i},{'Abs','Absolute'}))
297        OCS.Incremental = 0;
298        varargin(i) = [];
299
300    elseif any(strcmpi(varargin{i},{'SetPV','SetSP'}))
301        SetSPFlag = 1;
302        varargin(i) = [];
303    elseif any(strcmpi(varargin{i},{'NoSetPV','NoSetSP'}))
304        SetSPFlag = 0;
305        varargin(i) = [];
306
307    elseif any(strcmpi(varargin{i},{'GetPV','GetAM'}))
308        GetPVFlag = 1;
309        varargin(i)   = [];
310    elseif any(strcmpi(varargin{i},{'NoGetPV','NoGetAM'}))
311        GetPVFlag = 0;
312        varargin(i)   = [];
313
314    elseif strcmpi(varargin{i},'Simulator') || strcmpi(varargin{i},'Model')
315        ModeFlag = 'Simulator';
316        %OCSFlags = [OCSFlags varargin(i)];    % Don't maintain the mode field, it must be on the input field
317        InputFlags = [InputFlags varargin(i)];
318        varargin(i) = [];
319    elseif strcmpi(varargin{i},'Online')
320        ModeFlag = 'Online';
321        %OCSFlags = [OCSFlags varargin(i)];    % Don't maintain the mode field, it must be on the input field
322        InputFlags = [InputFlags varargin(i)];
323        varargin(i) = [];
324    elseif strcmpi(varargin{i},'Manual')
325        ModeFlag = 'Manual';
326        %OCSFlags = [OCSFlags varargin(i)];    % Don't maintain the mode field, it must be on the input field
327        InputFlags = [InputFlags varargin(i)];
328        varargin(i) = [];
329   
330    elseif strcmpi(varargin{i},'physics')
331        OCSFlags = [OCSFlags varargin(i)];
332        InputFlags = [InputFlags varargin(i)];
333        varargin(i) = [];
334    elseif strcmpi(varargin{i},'hardware')
335        OCSFlags = [OCSFlags varargin(i)];
336        InputFlags = [InputFlags varargin(i)];
337        varargin(i) = [];
338
339    elseif strcmpi(varargin{i},'FigureHandles')
340        OCS.Display = 1;
341        FigHandles = varargin{i+1};
342        if ~any(length(FigHandles) == [1 2  3 6])
343            error('Figure handles must be of length 1 or 2 for figures or 3 or 6 for axes.');
344        end
345        varargin(i+1) = [];
346        varargin(i)   = [];
347
348    elseif strcmpi(varargin{i},'CorrectorGain')
349        OCS.CorrectorGain = varargin{i+1};
350        varargin(i+1) = [];
351        varargin(i)   = [];
352
353    elseif strcmpi(varargin{i},'Tolerance')
354        OCS.Tolerance = varargin{i+1};
355        varargin(i+1) = [];
356        varargin(i)   = [];
357
358    elseif strcmpi(varargin{i},'RampSteps')
359        OCS.RampSteps = varargin{i+1};
360        varargin(i+1) = [];
361        varargin(i)   = [];
362
363    elseif strcmpi(varargin{i},'Archive')
364        % Just remove
365        varargin(i) = [];
366    elseif strcmpi(varargin{i},'NoArchive')
367        % Just remove
368        varargin(i) = [];
369    elseif strcmpi(varargin{i},'Struct')
370        % Just remove
371        varargin(i) = [];
372    elseif strcmpi(varargin{i},'Numeric')
373        % Just remove
374        varargin(i) = [];
375    end
376end
377
378OCSFlags = [OCSFlags {RespFlag} {DispFlag}];
379
380
381if ~OCSInputFlag
382    if iscell(varargin{1})
383        if isstruct(varargin{1}{1})
384            % BPM, CM
385            if length(varargin) < 2
386                error('Input parsing problem');
387            end
388            if ~iscell(varargin{1}) || ~iscell(varargin{2})
389                error('When using cell arrays BPM and CM inputs must all be cell arrays');
390            end
391            OCS.BPM = varargin{1};
392            OCS.CM = varargin{2};
393            varargin(1:2) = [];
394        else
395            % GoalOrbit, BPM, CM
396            if length(varargin) < 3
397                error('Input parsing problem');
398            end
399            OCS.GoalOrbit = varargin{1};
400            if ~iscell(varargin{2}) || ~iscell(varargin{3})
401                error('When using cell arrays BPM and CM inputs must all be cell arrays');
402            end
403            OCS.BPM = varargin{2};
404            OCS.CM = varargin{3};
405            varargin(1:3) = [];
406        end
407    elseif isstruct(varargin{1})
408        % BPM and CM are structures, Golden orbit is not
409        % Golden orbit could have been a string which has already been removed
410        if length(varargin) < 2
411            error('Input parsing problem: BPM and/or CM not found');
412        end
413        OCS.BPM = varargin{1};
414        varargin(1) = [];
415        if ischar(OCS.BPM)
416            FamilyName = OCS.BPM;
417            DeviceList = varargin{1};
418            if length(varargin) < 1
419                error('BPM device list must exist');
420            end
421            varargin(1) = [];
422            OCS.BPM = family2datastruct(FamilyName, DeviceList);
423        end
424        OCS.CM = varargin{1};
425        varargin(1) = [];
426        if ischar(OCS.CM)
427            FamilyName = OCS.CM;
428            if length(varargin) < 1
429                error('Corrector magnet device list must exist');
430            end
431            DeviceList = varargin{1};
432            varargin(1) = [];
433            OCS.CM = getsp(FamilyName, DeviceList, 'struct');
434        end
435    else
436        if isnumeric(varargin{1})
437            if length(varargin) < 3
438                error('Input parsing problem: GoalOrbit, BPM, CM not all found');
439            end
440            OCS.GoalOrbit = varargin{1};
441            varargin(1) = [];
442        else
443            if length(varargin) < 2
444                error('Input parsing problem: BPM and/or CM not found');
445            end
446        end
447
448        OCS.BPM = varargin{1};
449        varargin(1) = [];
450        if ischar(OCS.BPM)
451            FamilyName = OCS.BPM;
452            if isnumeric(varargin{1})
453                DeviceList = varargin{1};
454                varargin(1) = [];
455            else
456                DeviceList = [];
457            end
458            if length(varargin) < 1
459                error('BPM device list must exist');
460            end
461            OCS.BPM = family2datastruct(FamilyName, DeviceList);
462        end
463
464        OCS.CM = varargin{1};
465        varargin(1) = [];
466        if ischar(OCS.CM)
467            FamilyName = OCS.CM;
468            if length(varargin) < 1
469                error('Corrector magnget device list must exist');
470            end
471            if isnumeric(varargin{1})
472                DeviceList = varargin{1};
473                varargin(1) = [];
474            else
475                DeviceList = [];
476            end
477            OCS.CM = getsp(FamilyName, DeviceList, 'struct');
478        end
479    end
480end
481
482
483% Get NIter
484if length(varargin) >= 1
485    OCS.NIter = varargin{1};
486    varargin(1) = [];
487end
488if isempty(OCS.NIter)
489    OCS.NIter = DefaultNIter;
490end
491
492% Get SVDIndex
493if length(varargin) >= 1
494    OCS.SVDIndex = varargin{1};
495    varargin(1) = [];
496end
497if isempty(OCS.SVDIndex)
498    OCS.SVDIndex = DefaultSVDIndex;
499end
500
501
502% Get BPMWeight
503if length(varargin) >= 1
504    OCS.BPMWeight = varargin{1};
505    varargin(1) = [];
506end
507
508
509% Check BPM field
510if isempty(OCS.BPM)
511    OCS.BPM = {gethbpmfamily, getvbpmfamily};
512end
513
514% Check CM field
515if isempty(OCS.CM)
516    OCS.CM = {gethcmfamily,  getvcmfamily};
517end
518
519
520% Check the Display field
521if isempty(OCS.Display)
522    OCS.Display = DefaultDisplay;
523end
524
525
526% Check the corrector gain
527if isempty(OCS.CorrectorGain)
528    OCS.CorrectorGain = DefaultCorrectorGain;
529end
530
531
532% Check NIter
533if OCS.Incremental
534    if ~OCS.Display && OCS.NIter == 1
535        % Use OCS.NIter=0, since BPM data is not needed
536        OCS.NIter = 0;
537    end
538else
539    if OCS.NIter == 0
540        error('Number of iterations cannot be zero for absolute orbit changes');
541    end
542end
543
544
545% Make cell arrays if they are not already
546if ~iscell(OCS.BPM)
547    NoCellBPMFlag = 1;
548    OCS.BPM = {OCS.BPM};
549else
550    NoCellBPMFlag = 0;
551end
552if ~iscell(OCS.CM)
553    NoCellCMFlag = 1;
554    OCS.CM = {OCS.CM};
555    if isfield(OCS, 'CMWeight') && ~iscell(OCS.CMWeight)
556        OCS.CMWeight = {OCS.CMWeight};
557    end
558else
559    NoCellCMFlag = 0;
560end
561
562
563% Attach the flags
564OCS.Flags = OCSFlags;
565
566%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
567% End input parsing and checking %
568%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
569
570
571%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
572% Check for good status if online %
573%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
574for i = 1:length(OCS.BPM)
575    if strcmpi(getmode(OCS.BPM{i}),'Online')
576        [S, IndexList] = family2status(OCS.BPM{i});
577        if find(S==0)
578            tmp = questdlg({sprintf(...
579                'BPM family %s is showing %d element(s) with bad status.', OCS.BPM{i}.FamilyName, length(find(S==0))), ...
580                'Do you want to continue with orbit correction?'},...
581                'SETORBIT','YES','NO','NO');
582            if ~strcmpi(tmp,'YES')
583                return
584            end
585        end
586    end
587end
588for i = 1:length(OCS.CM)
589    if strcmpi(getmode(OCS.CM{i}),'Online')
590        [S, IndexList] = family2status(OCS.CM{i});
591        if find(S==0)
592            tmp = questdlg({sprintf(...
593                'Corrector family %s is showing %d element(s) with bad status.', OCS.CM{i}.FamilyName, length(find(S==0))), ...
594                'Do you want to continue with orbit correction?'},...
595                'SETORBIT','YES','NO','NO');
596            if ~strcmpi(tmp,'YES')
597                return
598            end
599        end
600    end
601end
602
603
604% Check BPMWeight
605if ~isfield(OCS, 'BPMWeight')
606    for i = 1:length(OCS.BPM)
607        OCS.BPMWeight{i} = [];
608    end
609end
610if ~iscell(OCS.BPMWeight)
611    OCS.BPMWeight = {OCS.BPMWeight};
612end
613
614
615
616%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
617% Build the goal orbit cell %
618%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
619if ischar(OCS.GoalOrbit)
620    GoalOrbitFlag = OCS.GoalOrbit;
621    OCS.GoalOrbit = [];
622    for i = 1:length(OCS.BPM)
623        if strcmpi(GoalOrbitFlag,'Golden')
624            tmp = getgolden(OCS.BPM{i}, 'Numeric');
625        elseif strcmpi(GoalOrbitFlag,'Offset')
626            tmp = getoffset(OCS.BPM{i}, 'Numeric');
627        else
628            error('Only golden and offset orbits are known')
629        end
630        OCS.GoalOrbit{i} = tmp;
631    end
632end
633if ~iscell(OCS.GoalOrbit)
634    OCS.GoalOrbit = {OCS.GoalOrbit};
635end
636
637
638%%%%%%%%%%%%%%%%%%%%%%
639% End of Input Setup %
640%%%%%%%%%%%%%%%%%%%%%%
641
642
643
644% Save the starting RF frequency
645% OCS.FitRFtest added by Laurent S. Nadolski
646% Has to work even if masterclock is off
647if OCS.FitRF ~= 0 && GetPVFlag
648    OCS.RF = getrf('Struct', InputFlags{:});
649end
650
651
652% Number of iterations (OCS.NIter can be 0 for display reasons with increment changes)
653if OCS.NIter == 0
654    NumberOfTrys = 1;
655else
656    NumberOfTrys = OCS.NIter;
657end
658
659
660%%%%%%%%%%%%%%%%%%%%%%%%%%%%
661% Build the starting orbit %
662%%%%%%%%%%%%%%%%%%%%%%%%%%%%
663for i = 1:length(OCS.BPM)
664    if OCS.NIter == 0
665        % Don't use BPM data for zero interations
666        OCS.BPM{i}.Data = zeros(size(OCS.BPM{i}.DeviceList,1),1);
667    else
668        if GetPVFlag
669            % Get new BPM data if not in calculate mode
670            OCS.BPM{i} = getpv(OCS.BPM{i}, 'Struct', InputFlags{:});
671        end
672    end
673end
674
675% For increment changes, convert the goal orbit to an absolute orbit
676if OCS.Incremental && OCS.NIter > 0
677    for i = 1:length(OCS.GoalOrbit)
678        OCS.GoalOrbit{i} = OCS.GoalOrbit{i} + OCS.BPM{i}.Data;
679    end
680   
681    % The incremental flag is always zero on exit because the orbits are absolute at this point
682    OCS.Incremental = 0;
683end
684
685
686
687% Interactively select singular value
688SVDquestion = 'Select Again';
689MorePlotsFlag = 0;
690while strcmp(SVDquestion,'Select Again')
691
692    %%%%%%%%%%%%%%%%%%%%%%%%%%%%
693    % Build the starting orbit %
694    %%%%%%%%%%%%%%%%%%%%%%%%%%%%
695    for i = 1:length(OCS.BPM)
696        if OCS.NIter == 0
697            % Don't use BPM data for zero interations
698            OCS.BPM{i}.Data = zeros(size(OCS.BPM{i}.DeviceList,1),1);
699        else
700            if GetPVFlag
701                % Get new BPM data if not in calculate mode
702                OCS.BPM{i} = getpv(OCS.BPM{i}, 'Struct', InputFlags{:});
703            end
704        end
705    end
706
707
708    % Get the present setpoints
709    if GetPVFlag
710        OCS.CM = getpv(OCS.CM, 'Struct', InputFlags{:});
711    end
712
713    % Compute the correction
714    [OCS, Smat, S, U, V] = orbitcorrectionmethods(OCS);
715
716    % Save the starting OCS (with possible CM & BPM list changes)
717    OCS0 = OCS;
718
719    if OCS.Display  % || length(FigHandles>=3)
720        [FigHandles, AxesHandles, OCS] = PreCorrectionDisplay(FigHandles, OCS0, OCS, Smat, S, U, V, NumberOfTrys, MorePlotsFlag, InputFlags);
721    else
722        SVDquestion = 'Correct Orbit';
723    end
724
725    if SetSPFlag && OCS.Display && length(FigHandles)<3
726        Units = get(0,'units');
727        if strcmpi(Units, 'Normalized')
728            fprintf('   Setting the command window units to pixels since the menu command fails with normalized units.\n');
729            set(0,'units','pixels');
730        end
731        if MorePlotsFlag == 0
732            tmp = menu('', ...
733                'Apply orbit correction', ...
734                'Change the number of singular values', ...
735                'Change the BPMs', ...
736                'Change the correctors', ...
737                'Plot more information (AT Model required)', ...
738                'Exit - No orbit correction');
739        else
740            tmp = menu('', ...
741                'Apply orbit correction', ...
742                'Change the number of singular values', ...
743                'Change the BPMs', ...
744                'Change the correctors', ...
745                'Close "more information plot"', ...
746                'Exit - No orbit correction');
747        end
748        if tmp == 6
749            fprintf('   Orbit not corrected\n');
750            SVDquestion = 'Correct not corrected';
751            SetSPFlag = 0;
752        elseif tmp == 1
753            SVDquestion = 'Correct Orbit';
754        elseif tmp == 2
755            % Change the singular values
756            def = {sprintf('[%d:%d]',OCS.SVDIndex(1),OCS.SVDIndex(end))};
757            answer=inputdlg({'Which singular values:'}, 'SETORBIT', 1, def);
758            if ~isempty(answer)
759                tmp = str2num(answer{1});
760
761                % Test for out-ot-range
762                if all(tmp<=size(V,2)) && ~isempty(tmp)
763                    OCS.SVDIndex = tmp;
764                else
765                    fprintf('   Singular value selection out-of-range.  Select again and try a new range.\n');
766                end
767            end
768        elseif tmp == 3
769            % Change BPMs
770            for i = 1:length(OCS.BPM)
771                List0 = OCS.BPM{i}.DeviceList;
772                ListTotal = family2dev(OCS.BPM{i}.FamilyName);
773                j = findrowindex(OCS.BPM{i}.DeviceList, ListTotal);
774                CheckedList = zeros(size(ListTotal,1),1);
775                CheckedList(j) = 1;
776                OCS.BPM{i}.DeviceList = editlist(ListTotal, OCS.BPM{i}.FamilyName, CheckedList);
777
778                [j,jNotFound] = findrowindex(OCS.BPM{i}.DeviceList, List0);
779                if isempty(jNotFound)
780                    OCS.GoalOrbit{i} = OCS.GoalOrbit{i}(j);
781                    if ~isempty(OCS.BPMWeight{i}) && isvector(OCS.BPMWeight{i})
782                        OCS.BPMWeight{i} = OCS.BPMWeight{i}(j);
783                    end
784                else
785                    % New BPMs were added
786                    if any(strcmpi(OCS.Flags,'Golden'))
787                        OCS.GoalOrbit{i} = getgolden(OCS.BPM{i}, 'Numeric');
788                    elseif any(strcmpi(OCS.Flags,'Offset'))
789                        OCS.GoalOrbit{i} = getoffset(OCS.BPM{i}, 'Numeric');
790                    else
791                        error('Unknown goal orbit for the new BPMs');
792                    end
793                    if ~isempty(OCS.BPMWeight{i})
794                        if all(OCS.BPMWeight{i} == max(OCS.BPMWeight{i}))
795                            % If all the weights are the same, then the new BPMs get the same weight
796                            OCS.BPMWeight{i} = OCS.BPMWeight{i}(1) * ones(size(OCS.BPM{i}.DeviceList,1),1);
797                        else
798                            error('Unknown BPM weights for new BPMs');
799                        end
800                    end
801                end
802            end
803        elseif tmp == 4
804            % Change correctors
805            for i = 1:length(OCS.CM)
806                ListTotal = family2dev(OCS.CM{i}.FamilyName);
807                j = findrowindex(OCS.CM{i}.DeviceList, ListTotal);
808                CheckedList = zeros(size(ListTotal,1),1);
809                CheckedList(j) = 1;
810                OCS.CM{i}.DeviceList = editlist(ListTotal, OCS.CM{i}.FamilyName, CheckedList);
811            end
812        elseif tmp == 5
813            if MorePlotsFlag == 0
814                MorePlotsFlag = 1;
815            else
816                MorePlotsFlag = 0;
817                close(FigHandles(2));
818                FigHandles = [FigHandles(1); NaN];
819
820                % Make figure 1 a little wider
821                p = get(FigHandles(1), 'Position');
822                set(FigHandles(1), 'Position', [p(1)-.1*p(3) p(2) p(3)+.1*p(3) p(4)]);
823            end
824        end
825    else
826        SVDquestion = 'Get out of loop';
827    end
828end
829
830
831%%%%%%%%%%%%%%%%%%%%%%
832% Exit if ~SetSPFlag %
833%%%%%%%%%%%%%%%%%%%%%%
834if ~SetSPFlag
835    %% Put Delta into OCS.CM (don't do this since setorbit can be called multiple times before correcting)
836    %for i = 1:length(OCS.CM)
837    %    OCS.CM{i}.Data = OCS.CM{i}.Data + OCS.CM{i}.Delta;
838    %end
839    %if OCS.FitRF
840    %    OCS.RF.Data = OCS.RF.Data + OCS.DeltaRF;
841    %end
842
843    % Remove the cell array if it was not input as a cell array
844    if NoCellBPMFlag
845        OCS.BPM = OCS.BPM{1};
846        OCS0.BPM = OCS0.BPM{1};
847
848        OCS.GoalOrbit = OCS.GoalOrbit{1};
849        OCS0.GoalOrbit = OCS0.GoalOrbit{1};
850
851        OCS.BPMWeight = OCS.BPMWeight{1};
852        OCS0.BPMWeight = OCS0.BPMWeight{1};
853    end
854    if NoCellCMFlag
855        OCS.CM = OCS.CM{1};
856        OCS0.CM = OCS0.CM{1};
857
858        if isfield(OCS, 'CMWeight')
859            OCS.CMWeight = OCS.CMWeight{1};
860            OCS0.CMWeight = OCS0.CMWeight{1};
861        end
862    end
863    return;
864end
865
866
867
868%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
869% Iterate on orbit correction %
870%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
871
872if ~isfield(OCS, 'MinimumPeriod')
873    OCS.MinimumPeriod = 0;
874end
875if isempty(OCS.MinimumPeriod)
876    OCS.MinimumPeriod = 0;
877end
878
879       
880% Running flag
881RingSetOrbit.RunFlag = 1;
882setappdata(0, 'RingSetOrbit', RingSetOrbit);
883
884OCS.NCorrections = 0;
885for iloop = 1:NumberOfTrys
886    tic;
887
888    % The 1st iteration is already computed
889    if iloop > 1
890        % Build the new starting orbit
891        for i = 1:length(OCS.BPM)
892            OCS.BPM{i} = getpv(OCS.BPM{i}, 'Struct', InputFlags{:});
893        end
894
895        % Compute the correction
896        OCS = orbitcorrectionmethods(OCS, Smat, S, U, V);
897    end
898
899
900    % Tolerance check
901    for i = 1:length(OCS.BPM)
902        TolFlag(i) = std(OCS.BPM{i}.Data(:) - OCS.GoalOrbit{i}(:)) < OCS.Tolerance;
903    end
904    if all(TolFlag)
905        break;
906    end
907
908   
909    % Put Delta into OCS.CM & OCS.RF
910    for i = 1:length(OCS.CM)
911        OCS.CM{i}.Data = OCS.CM{i}.Data + OCS.CorrectorGain * OCS.CM{i}.Delta;
912    end
913    if OCS.FitRF
914        OCS.RF.Data = OCS.RF.Data + OCS.CorrectorGain * OCS.DeltaRF;
915    end
916
917    % Check corrector power supply limits
918    for i = 1:length(OCS.CM)
919        MinSP = minsp(OCS.CM{i});
920        MaxSP = maxsp(OCS.CM{i});
921       
922        % Since the Max or Min sign is really arbitary, any(OCS.CM{i}.Data > MaxSP) will not work
923        % For instance, a max in hardware units can be a min in physics units.
924        % It's better to check if it's between the max and min
925        [Tmp, SortIndex] = sort([MinSP OCS.CM{i}.Data MaxSP],2);
926        if any(SortIndex(:,2) ~= 2)
927            icm = find(SortIndex(:,2) ~= 2);
928            for j = 1:length(icm)
929                fprintf('   Setting %s(%d,%d) to %f would exceed [%f %f] %s range.\n', OCS.CM{i}.FamilyName, OCS.CM{i}.DeviceList(icm(j),:), OCS.CM{i}.Data(icm(j)), MinSP(icm(j)), MaxSP(icm(j)), OCS.CM{i}.UnitsString);
930            end
931            fprintf('   Orbit correction stopped on iteration %d.\n   A power supply limit would have been exceeded!\n', iloop);
932            RingSetOrbit.RunFlag = 0;
933            setappdata(0, 'RingSetOrbit', RingSetOrbit);
934            ErrorFlag = 1;
935            break;
936            %return;
937        end
938    end
939    if ErrorFlag
940        break;
941    end
942
943
944    %if OCS.Display
945    %    if OCS.NIter > 1
946    %        fprintf('   Iteration %d. Changing the correctors (%s)\n', iloop, datestr(clock, 0));
947    %        if OCS.FitRF
948    %            fprintf('   Iteration %d. Changing the RF frequency by %d %s\n', iloop, OCS.DeltaRF, OCS.RF.UnitsString);
949    %        end
950    %    else
951    %        fprintf('   Setting the correctors (%s)\n', datestr(clock, 0));
952    %        if OCS.FitRF
953    %            fprintf('   Changing the RF frequency by %d %s (%s)\n', OCS.DeltaRF, OCS.RF.UnitsString, datestr(clock, 0));
954    %        end
955    %    end
956    %end
957   
958    % Since power supplies get out of sync, it can be useful
959    % to set the power supplies in smaller steps.
960    if OCS.RampSteps == 1 || iloop > 1
961        % Apply correction in 1 step
962       
963        % Set the RF frequency
964        if OCS.FitRF
965            steprf(OCS.DeltaRF, -1, InputFlags{:});
966        end
967
968        % Set the correctors in one step
969        setpv(OCS.CM, -2, InputFlags{:});
970
971    else
972
973        % Apply correction slowly
974        CM  = OCS.CM;
975        CM1 = getpv(OCS.CM,'Struct');
976        CM2 = OCS.CM;
977
978        if OCS.FitRF
979            dRF = OCS.DeltaRF / OCS.RampSteps;
980        end
981
982        for j = 1:OCS.RampSteps
983            if j == OCS.RampSteps
984                WaitFlag = -2;
985            else
986                WaitFlag = -1;
987            end
988           
989            if OCS.FitRF
990                steprf(dRF, -1, InputFlags{:});
991            end
992
993            for i = 1:length(OCS.CM)
994                CM{i}.Data = CM1{i}.Data + (CM2{i}.Data - CM1{i}.Data)*(j/OCS.RampSteps);
995                setpv(CM{i}, WaitFlag, InputFlags{:});
996            end
997        end
998    end
999   
1000
1001    OCS.NCorrections = iloop;            % Count the actual number of corrections made
1002    sleep(ExtraDelay);
1003
1004       
1005    %%%%%%%%%%%%%%%%%%%%%%%%%
1006    % Build the final orbit %
1007    %%%%%%%%%%%%%%%%%%%%%%%%%
1008    for i = 1:length(OCS.BPM)
1009        if OCS.NIter > 0
1010            OCS.BPM{i}.Data = getpv(OCS.BPM{i}, 'Numeric', InputFlags{:});
1011        end
1012    end
1013
1014
1015    % Get the present setpoints
1016    % Some accelerators might have digitizing errors that gets picked up with a reread
1017    OCS.CM = getpv(OCS.CM, 'Struct', InputFlags{:});
1018
1019    if OCS.FitRF
1020        OCS.RF = getrf('Struct', InputFlags{:});
1021    end
1022
1023
1024    % Display final result if OCS.Display, more than 0 iterations, and a setpoint change was made
1025    %if (OCS.Display | length(FigHandles>=4)) & OCS.NIter & SetSPFlag
1026    if OCS.Display && OCS.NIter && SetSPFlag
1027        PostCorrectionDisplay(AxesHandles, OCS0, OCS, Smat, S, U, V, iloop, NumberOfTrys, MorePlotsFlag, InputFlags);
1028    end
1029
1030    % Update timestamp
1031    if OCS.Display && isfield(OCS,'Handles') && isfield(OCS.Handles, 'TimeStamp') && ~isempty(OCS.Handles.TimeStamp)
1032        set(OCS.Handles.TimeStamp, 'String', datestr(clock,0));
1033        drawnow;
1034    end
1035   
1036   
1037    if iloop ~= NumberOfTrys
1038        % Check if another application is trying to change a setting
1039        [StopFlag, OCS, Smat, S, U, V, AxesHandles, MorePlotsFlag] = answersetorbitcall(OCS, Smat, S, U, V, AxesHandles, InputFlags);
1040        if StopFlag
1041            break;
1042        end
1043
1044
1045        % Check beam current (this might be machine dependent)
1046        if getdcct < DCCTLOW
1047            fprintf('   Orbit correction stopped on iteration %d.   Beam current is below .05 milliampere!\n', iloop);
1048            break;
1049        end
1050
1051       
1052        % Set the minimum update period
1053        while toc < OCS.MinimumPeriod
1054            if (OCS.MinimumPeriod-toc) > .3
1055                sleep(.3);
1056            else
1057                sleep(OCS.MinimumPeriod - toc);
1058            end
1059
1060            % Check for a stop request or change to the minimum update period
1061            [StopFlag, OCS, Smat, S, U, V, AxesHandles, MorePlotsFlag] = answersetorbitcall(OCS, Smat, S, U, V, AxesHandles, InputFlags);
1062            if StopFlag
1063                break;
1064            end
1065        end
1066    end
1067end
1068
1069
1070% Orbit correction finished
1071RingSetOrbit.RunFlag = 0;
1072setappdata(0, 'RingSetOrbit', RingSetOrbit);
1073
1074
1075% For multiple iterations put the total change in the .Delta & .DeltaRF fields
1076for i = 1:length(OCS.CM)
1077    OCS.CM{i}.Delta = OCS.CM{i}.Data - OCS0.CM{i}.Data;
1078end
1079if OCS.FitRF
1080    OCS.DeltaRF = OCS.RF.Data - OCS0.RF.Data;
1081end
1082
1083
1084% Remove the cell array if the input was not a cell
1085if NoCellBPMFlag
1086    OCS.BPM = OCS.BPM{1};
1087    OCS0.BPM = OCS0.BPM{1};
1088
1089    OCS.GoalOrbit = OCS.GoalOrbit{1};
1090    OCS0.GoalOrbit = OCS0.GoalOrbit{1};
1091
1092    OCS.BPMWeight = OCS.BPMWeight{1};
1093    OCS0.BPMWeight = OCS0.BPMWeight{1};
1094end
1095if NoCellCMFlag
1096    OCS.CM = OCS.CM{1};
1097    OCS0.CM = OCS0.CM{1};
1098   
1099    if isfield(OCS, 'CMWeight')
1100        OCS.CMWeight = OCS.CMWeight{1};
1101        OCS0.CMWeight = OCS0.CMWeight{1};
1102    end
1103end
1104
1105
1106% if OCS.Display
1107%     fprintf('   Orbit correction complete (%s)\n', datestr(clock, 0));
1108% end
1109
1110
1111%%%%%%%%%%%%%%%%%%%
1112% End of Setorbit %
1113%%%%%%%%%%%%%%%%%%%
1114
1115
1116
1117%%%%%%%%%%%%%%%%%%%%%%%%%%
1118% Ring/Answer Subroutine %
1119%%%%%%%%%%%%%%%%%%%%%%%%%%
1120function [StopFlag, OCS, Smat, S, U, V, FigureHandles, MorePlotsFlag] = answersetorbitcall(OCS, Smat, S, U, V, FigureHandles, InputFlags)
1121
1122StopFlag = 0;
1123MorePlotsFlag = 0;
1124RingSetOrbit = getappdata(0, 'RingSetOrbit');
1125
1126if ~isempty(RingSetOrbit)
1127
1128    if isfield(RingSetOrbit, 'RunFlag')
1129        if RingSetOrbit.RunFlag == -1
1130            StopFlag = 1;
1131        end
1132        %RingSetOrbit = rmfield(RingSetOrbit, 'RunFlag');
1133        %setappdata(0, 'RingSetOrbit', RingSetOrbit);
1134    end
1135
1136    if isfield(RingSetOrbit, 'MinimumPeriod')
1137        OCS.MinimumPeriod = RingSetOrbit.MinimumPeriod;
1138        if isempty(OCS.MinimumPeriod)
1139            OCS.MinimumPeriod = 0;
1140        end
1141        RingSetOrbit = rmfield(RingSetOrbit, 'MinimumPeriod');
1142        setappdata(0, 'RingSetOrbit', RingSetOrbit);
1143    end
1144
1145    if isfield(RingSetOrbit, 'Display')
1146        OCS.Display = RingSetOrbit.Display;
1147        RingSetOrbit = rmfield(RingSetOrbit, 'Display');
1148        setappdata(0, 'RingSetOrbit', RingSetOrbit);
1149    end
1150
1151    if isfield(RingSetOrbit, 'CorrectorGain')
1152        OCS.CorrectorGain = RingSetOrbit.CorrectorGain;
1153        RingSetOrbit = rmfield(RingSetOrbit, 'CorrectorGain');
1154        setappdata(0, 'RingSetOrbit', RingSetOrbit);
1155    end
1156
1157    if isfield(RingSetOrbit, 'FigureHandles')
1158        FigureHandles = RingSetOrbit.FigureHandles;
1159        RingSetOrbit = rmfield(RingSetOrbit, 'FigureHandles');
1160        setappdata(0, 'RingSetOrbit', RingSetOrbit);
1161
1162        if length(FigureHandles) == 6
1163            drawmoreplots(FigureHandles(4:6), OCS, Smat, S, U, V);
1164            %MorePlotsFlag = 1;
1165        end
1166    end
1167
1168
1169    if isfield(RingSetOrbit, 'FitRF')
1170        OCS.FitRF = RingSetOrbit.FitRF;
1171        RingSetOrbit = rmfield(RingSetOrbit, 'FitRF');
1172        setappdata(0, 'RingSetOrbit', RingSetOrbit);
1173       
1174        if OCS.FitRF == 1
1175            % Include the RF frequency next time
1176            OCS.RF = getrf('Struct', InputFlags{:});
1177            [OCS, Smat, S, U, V] = orbitcorrectionmethods(OCS);  % Get new S, U, V matrices
1178        else
1179            % Don't include the RF frequency next time
1180            OCS.FitRF = 0;
1181            [OCS, Smat, S, U, V] = orbitcorrectionmethods(OCS);  % Get new S, U, V matrices
1182        end
1183    end
1184   
1185end
1186
1187
1188
1189%%%%%%%%%%%%%%%%%%%%%%%%%%%
1190%  Pre-correction display %
1191%%%%%%%%%%%%%%%%%%%%%%%%%%%
1192function [H, Haxis, OCS] = PreCorrectionDisplay(H, OCS0, OCS, Smat, S, U, V, NumberOfTrys, MorePlotsFlag, InputFlags)
1193
1194% Build the orbit vector
1195StartOrbitVec = [];
1196Orbit0Vec = [];
1197GoalOrbitVec = [];
1198BPMWeight = [];
1199for i = 1:length(OCS.BPM)
1200    StartOrbitVec = [StartOrbitVec; OCS.BPM{i}.Data];
1201    Orbit0Vec     = [Orbit0Vec;     OCS.BPM{i}.Data];
1202    GoalOrbitVec  = [GoalOrbitVec;  OCS.GoalOrbit{i}];
1203
1204    if isempty(OCS.BPMWeight{i})
1205        BPMWeight = [BPMWeight; ones(length(OCS.BPM{i}.Data),1)];
1206    else
1207        BPMWeight = [BPMWeight; OCS.BPMWeight{i}(:)];
1208    end
1209end
1210
1211% Plot some stuff
1212L = getfamilydata('Circumference');
1213if isempty(L)
1214    global THERING
1215    L = findspos(THERING, length(THERING)+1);
1216end
1217
1218
1219if isempty(H)
1220    HCF = get(0, 'CurrentFigure');
1221    if isempty(HCF)
1222        H = [gcf; NaN];
1223    else
1224        if rem(HCF,1)==0
1225            H = [HCF(1); NaN];
1226        else
1227            H = [figure; NaN];
1228        end
1229    end
1230    %drawnow
1231    subfig(2,2,2, H(1));
1232    p = get(H(1), 'Position');
1233    set(H(1), 'Position', [p(1) p(2)-.8*p(4) p(3) p(4)+.8*p(4)]);
1234end
1235
1236
1237if length(H) < 3
1238    figure(H(1));
1239    clf reset
1240    Haxis(1) = subplot(3,1,1);
1241    Haxis(2) = subplot(3,1,2);
1242    Haxis(3) = subplot(3,1,3);
1243    yaxesposition(1.05);
1244    orient portrait
1245else
1246    Haxis = H;
1247end
1248
1249
1250ColorOrderMat = get(gca,'ColorOrder');
1251
1252
1253%%%%%%%%%%%%%%%%%%%%%%%
1254% Change in corrector %
1255%%%%%%%%%%%%%%%%%%%%%%%
1256axes(Haxis(1));
1257for i4 = 1:length(OCS.CM)
1258    CMpos = getspos(OCS.CM{i4});
1259    [CMpos,isort] = sort(CMpos);
1260
1261    % Percentage from max
1262    %CMmax = maxsp(OCS.CM{i4});
1263    %plot(CMpos, 100*OCS.CM{i4}.Delta./CMmax, '.-','Color', ColorOrderMat(mod(i4,size(ColorOrderMat,1)),:));
1264    %%plot(CMpos, 100*OCS.CM{i4}.Delta./CMmax,'-square','Color', ColorOrderMat(mod(i4,size(ColorOrderMat,1)),:), 'Markersize',3, 'MarkerFaceColor', ColorOrderMat(mod(i4,size(ColorOrderMat,1)),:));
1265    %LabelCell4{i4} = sprintf('%s', OCS.CM{i4}.FamilyName);
1266
1267    % Absolute corrector change
1268    plot(CMpos, OCS.CM{i4}.Delta(isort), '.-','Color', ColorOrderMat(mod(i4,size(ColorOrderMat,1)),:));
1269    LabelCell4{i4} = sprintf('%s [%s]', OCS.CM{i4}.FamilyName, OCS.CM{i4}.UnitsString);
1270    hold on;
1271end
1272hold off;
1273if length(OCS.CM) == 1
1274    %ylabel(sprintf('{\\Delta}%s [%%Max]', OCS.CM{1}.FamilyName));
1275    ylabel(sprintf('\\Delta %s [%s]', OCS.CM{1}.FamilyName, OCS.CM{1}.UnitsString));
1276else
1277    %ylabel('\Delta Corrector [%Max]');
1278    ylabel('\Delta Corrector');
1279    h_legend = legend(LabelCell4, 0);
1280    set(h_legend, 'FontSize', 8);
1281    set(h_legend, 'UserData', 'Axes1');
1282end
1283
1284%if NumberOfTrys == 1
1285if OCS.FitRF
1286    title({sprintf('\\DeltaRF = %g %s   SV[%d out of %d]', OCS.DeltaRF, OCS.RF.UnitsString, max(OCS.SVDIndex), length(S)), 'Pre-Orbit Correction'});
1287else
1288    title({sprintf('SV[%d out of %d]', max(OCS.SVDIndex), length(S)), 'Pre-Orbit Correction'});
1289end
1290
1291%xlabel('Position [Meters]');
1292xaxis([0 L]);
1293%set(gca,'XTickLabel','');
1294
1295
1296
1297%%%%%%%%%%%%%%%%%%%%
1298% Plot Orbit Error %
1299%%%%%%%%%%%%%%%%%%%%
1300axes(Haxis(2));
1301for i = 1:length(OCS.BPM)
1302    BPMpos = getspos(OCS.BPM{i});
1303    [BPMpos, isort] = sort(BPMpos);
1304    plot(BPMpos, OCS.BPM{i}.Data(isort) - OCS.GoalOrbit{i}(isort),'.-','Color', ColorOrderMat(mod(i,size(ColorOrderMat,1)),:));
1305    hold on;
1306    LabelCell2{i} = sprintf('%s [%s]', OCS.BPM{i}.FamilyName, OCS.BPM{i}.UnitsString);
1307end
1308hold off
1309if length(LabelCell2) == 1
1310    ylabel(sprintf('%s Starting Error [%s]', OCS.BPM{1}.FamilyName, OCS.BPM{1}.UnitsString));
1311else
1312    ylabel('Starting Orbit Error');
1313    h_legend = legend(LabelCell2, 0);
1314    set(h_legend, 'FontSize', 8);
1315    set(h_legend, 'UserData', 'Axes2');
1316end
1317%title(sprintf('Orbit Error Before Correction (Iteration 1 of %d)', NumberOfTrys));
1318%xlabel('Position [Meters]');
1319xaxis([0 L]);
1320%set(gca,'XTickLabel','');
1321
1322
1323
1324%%%%%%%%%%%%%%%%%%%%%%
1325% Predicted Residual %
1326%%%%%%%%%%%%%%%%%%%%%%
1327axes(Haxis(3));
1328
1329for i = 1:length(OCS.BPM)
1330    BPMpos = getspos(OCS.BPM{i});
1331    [BPMpos, isort] = sort(BPMpos);
1332
1333    % S-mat prediction: OrbitDelta + Error
1334    plot(BPMpos, OCS.BPM{i}.PredictedOrbitDelta(isort) + (OCS.BPM{i}.Data(isort)-OCS.GoalOrbit{i}(isort)),'.-','Color', ColorOrderMat(mod(i,size(ColorOrderMat,1)),:));
1335    hold on;
1336    LabelCell2{i} = sprintf('%s [%s]', OCS.BPM{i}.FamilyName, OCS.BPM{i}.UnitsString);
1337end
1338hold off
1339if length(LabelCell2) == 1
1340    ylabel(sprintf('%s Residual [%s]', OCS.BPM{1}.FamilyName, OCS.BPM{1}.UnitsString));
1341else
1342    ylabel('Orbit Residual');
1343    h_legend = legend(LabelCell2, 0);
1344    set(h_legend, 'FontSize', 8);
1345    set(h_legend, 'UserData', 'Axes3');
1346end
1347%title('Predicted Orbit Residual (by the Response Matrix)');
1348xlabel('Position [Meters]');
1349xaxis([0 L]);
1350
1351
1352% Add TimeStamp labels
1353if length(H) < 3
1354    OCS.Handles.TimeStamp = addlabel(1, 0, datestr(OCS.BPM{1}.TimeStamp,0));
1355
1356    %if OCS.FitRF
1357    %    OCS.Handles.RF = addlabel(0, 0, sprintf('RF frequency will be changed by  %g %s', OCS.DeltaRF, OCS.RF.UnitsString));
1358    %end
1359end
1360
1361
1362
1363
1364if MorePlotsFlag || length(H)==6
1365
1366    %%%%%%%%%%%%%%%%
1367    % 3 More Plots %
1368    %%%%%%%%%%%%%%%%
1369
1370    if length(H) < 3
1371        if isnan(H(2))
1372            H(2) = H(1) + 1;
1373            subfig(2,2,1,H(2));
1374            p = get(H(2), 'Position');
1375            set(H(2), 'Position', [p(1) p(2)-.8*p(4) p(3) p(4)+.8*p(4)]);
1376            p = get(H(2), 'Position');
1377            set(H(2), 'Position', [p(1)+.2*p(3) p(2) p(3)-.1*p(3) p(4)]);
1378
1379            p = get(H(1), 'Position');
1380            set(H(1), 'Position', [p(1)+.1*p(3) p(2) p(3)-.1*p(3) p(4)]);
1381        end
1382
1383        figure(H(2));
1384        clf reset
1385
1386        Haxis(4) = subplot(3,1,1);
1387        Haxis(5) = subplot(3,1,2);
1388        Haxis(6) = subplot(3,1,3);
1389        yaxesposition(1.05);
1390        orient portrait
1391    end
1392
1393    drawmoreplots(Haxis(4:6), OCS, Smat, S, U, V);
1394end
1395
1396drawnow;
1397
1398
1399%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1400%  End pre-correction display  %
1401%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1402
1403
1404
1405
1406function drawmoreplots(Haxis, OCS, Smat, S, U, V)
1407
1408
1409%%%%%%%%%%%%%%%%
1410% 3 More Plots %
1411%%%%%%%%%%%%%%%%
1412
1413%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1414% Compute Orbit Error & CM strength vs SVD Number %
1415%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1416
1417% Print wait messege
1418%plot([0 1],[0 1],'w');
1419%UnitsString = get(gca,'units');
1420%set(gca,'units','characters');
1421%p = get(gca,'Position');
1422%set(gca,'XTick',[]); set(gca,'YTick',[]); cla; title(' '); xlabel(' '); ylabel(' ');
1423%set(gca,'box','on');
1424%Top = floor(p(4));
1425%
1426%text(4,Top-4,sprintf('Please wait ...'),'units','characters');
1427%text(4,Top-6,sprintf('Computing correction performance'),'units','characters');
1428%text(4,Top-7,sprintf('   as a function of singular value number.'),'units','characters');
1429%set(gca, 'units', UnitsString);
1430%drawnow;
1431
1432
1433% The total kick as a function of SV
1434hbar = waitbar(0, 'Computing Orbit Change vs SVD#.  Please wait ...');
1435warning off;
1436LastGoodSvalue = 1;
1437OCStmp = OCS;
1438N = length(S);
1439for i = 1:N
1440    lastwarn('');
1441    waitbar(i/N);
1442
1443    OCStmp.SVDIndex = 1:i;
1444    OCStmp = orbitcorrectionmethods(OCStmp, Smat, S, U, V);
1445
1446
1447    % RMS orbit change of the corrector magnets
1448    for j = 1:length(OCS.CM)
1449        if isempty(lastwarn)
1450            CMSTDvec{j}(i) = std(OCStmp.CM{j}.Delta);
1451            CMTotal(j,i) = sum(abs(OCStmp.CM{j}.Delta));
1452        else
1453            CMSTDvec{j}(i) = NaN;
1454            CMTotal(j,i) = NaN;
1455        end
1456
1457
1458        % S-mat prediction residual: PredictedOrbitData + Error
1459        BPMresidual(j,i) = std(OCStmp.BPM{j}.PredictedOrbitDelta + (OCStmp.BPM{j}.Data-OCStmp.GoalOrbit{j}));
1460    end
1461
1462    if isempty(lastwarn)
1463        LastGoodSvalue = i;
1464        DeltaRFvec(i,1) = OCStmp.DeltaRF;
1465    else
1466        DeltaRFvec(i,1) = NaN;
1467        %fprintf('\n   S-value number %d warning: %s', i, lastwarn);
1468    end
1469end
1470try
1471    close(hbar);
1472catch
1473end
1474
1475
1476warning on;
1477if LastGoodSvalue ~= length(S)
1478    fprintf('   Computational warning for choosing singular values above %d. \n', LastGoodSvalue);
1479end
1480
1481
1482%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1483% CM strength vs SVD number %
1484%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1485iSVDremove = 1:length(S);
1486[tmp1, tmp2, i] = intersect(OCS.SVDIndex, iSVDremove);
1487iSVDremove(i) = [];
1488
1489for i = 1:length(OCS.CM)
1490    LabelCellCM{i} = sprintf('%s [%s]', OCS.CM{i}.FamilyName, OCS.CM{i}.UnitsString);
1491end
1492if OCS.FitRF
1493    %(Haxis(1));
1494    [ax, h1, h2] = plotyy(Haxis(1), 1:length(S), CMTotal, 1:length(S), DeltaRFvec, @plot, @plot);
1495    set(get(ax(2),'Ylabel'),'String',sprintf('\\DeltaRF Frequency [%s]', OCS.RF.UnitsString), 'Color',[.5 0 0]);
1496    set(h1,'LineStyle','-');
1497    set(h1,'Marker','.');
1498    set(h1,'MarkerSize',6);
1499    set(h2,'LineStyle','-');
1500    set(h2,'Color',[.5 0 0]);
1501    set(ax(2),'YColor',[.5 0 0]);
1502    set(h2,'Marker','.');
1503    set(h2,'MarkerSize',6);
1504    %set(get(ax(1),'XLabel'),'String', 'Singular Value Number');
1505    %set(get(ax(1),'Title'), 'String', 'Total Kick Strength');
1506
1507    set(ax(1),'XLim', [0 length(S)]);
1508    set(ax(2),'XLim', [0 length(S)]);
1509
1510    set(get(ax(1),'XLabel'),'String', '');
1511    set(get(ax(2),'XLabel'),'String', '');
1512    %set(ax(1),'XTickLabel', '');
1513    %set(ax(2),'XTickLabel', '');
1514
1515    set(get(ax(1),'title'),'string', {'Performance vs. Number of Singular Values',sprintf('Based on %s Orbit',datestr(OCS.BPM{1}.TimeStamp,0))});
1516
1517    if length(LabelCellCM) == 1
1518        set(get(ax(1),'YLabel'),'String',sprintf('\\Sigma \\mid%s\\mid [%s]', OCS.CM{1}.FamilyName, OCS.CM{1}.UnitsString));
1519    else
1520        set(get(ax(1),'YLabel'),'String',sprintf('\\Sigma \\midCM\\mid'));
1521        %h_legend = legend(Haxis(1), LabelCellCM, 0);
1522        %set(h_legend, 'FontSize', 8);
1523        %set(h_legend, 'UserData', 'Axes4');
1524        AxePosition = get(ax(2),'Position');
1525        set(ax(1),'Position', AxePosition);
1526    end
1527else
1528    %semilogy(1:length(S), CMTotal, '.-');
1529    plot(Haxis(1), 1:length(S), CMTotal, '-');
1530    hold(Haxis(1), 'on');
1531    plot(Haxis(1), OCS.SVDIndex, CMTotal(:,OCS.SVDIndex), 's', 'markersize',2);
1532    plot(Haxis(1), iSVDremove,   CMTotal(:,iSVDremove),   'sr','markersize',2);
1533    hold(Haxis(1), 'off');
1534
1535    if length(LabelCellCM) == 1
1536        ylabel(Haxis(1), sprintf('\\Sigma \\mid%s\\mid [%s]', OCS.CM{1}.FamilyName, OCS.CM{1}.UnitsString));
1537    else
1538        ylabel(Haxis(1), '\Sigma \midCM\mid');
1539        %h_legend = legend(Haxis(1), LabelCellCM, 0);
1540        %set(h_legend, 'FontSize', 8);
1541        %set(h_legend, 'UserData', 'Axes4');
1542    end
1543    %xlabel(Haxis(1), 'Singular Value Number');
1544    title(Haxis(1), {'Performance vs. Number of Singular Values',sprintf('Based on %s Orbit',datestr(OCS.BPM{1}.TimeStamp,0))});
1545   
1546    axis(Haxis(1), 'tight');
1547    a = axis(Haxis(1));
1548    axis(Haxis(1), [0 length(S) a(3:4)]);
1549    %set(gca,'XTickLabel','');
1550end
1551
1552
1553%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1554% Plot Orbit Error vs SVD Number %
1555%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1556%axes(Haxis(2));
1557ColorOrderMat = get(Haxis(2),'ColorOrder');
1558for i = 1:length(OCS.BPM)
1559    %BPMpos = getspos(OCS.BPM{i});
1560    %semilogy(1:length(S), CMSTDvec{i},'.-','Color', ColorOrderMat(mod(i,size(ColorOrderMat,1)),:));
1561    plot(Haxis(2), 1:length(S), BPMresidual(i,:),'-', 'Color', ColorOrderMat(mod(i,size(ColorOrderMat,1)),:));
1562    hold(Haxis(2), 'on');
1563    plot(Haxis(2), OCS.SVDIndex, BPMresidual(i,OCS.SVDIndex), 's', 'markersize',2, 'Color', ColorOrderMat(mod(i,size(ColorOrderMat,1)),:));
1564    plot(Haxis(2), iSVDremove,   BPMresidual(i,iSVDremove),   'sr','markersize',2);
1565   
1566    LabelCell2{i} = sprintf('%s [%s]', OCS.BPM{i}.FamilyName, OCS.BPM{i}.UnitsString);
1567end
1568hold(Haxis(2), 'off');
1569if length(LabelCell2) == 1
1570    ylabel(Haxis(2), sprintf('STD %s [%s]', OCS.BPM{1}.FamilyName, OCS.BPM{1}.UnitsString));
1571else
1572    ylabel(Haxis(2), 'std(Residual)');
1573    %h_legend = legend(Haxis(2), LabelCell2, 0);
1574    %set(h_legend, 'FontSize', 8);
1575    %set(h_legend, 'UserData', 'Axes5');
1576end
1577%title(Haxis(2), 'Standard Deviation of the Predicted Orbit Residual');
1578%xlabel(Haxis(2), 'Singular Value Number');
1579
1580axis(Haxis(2), 'tight');
1581a = axis(Haxis(2));
1582axis(Haxis(2), [0 length(S) a(3:4)]);
1583%set(gca,'XTickLabel','');
1584
1585
1586%%%%%%%%%%%%%%%%%%%%%%%%
1587% Plot singular values %
1588%%%%%%%%%%%%%%%%%%%%%%%%
1589axes(Haxis(3));
1590semilogy(Haxis(3), S, '-b');
1591hold(Haxis(3), 'on');
1592semilogy(Haxis(3), OCS.SVDIndex, S(OCS.SVDIndex), 'sb', 'markersize',2);
1593semilogy(Haxis(3), iSVDremove,   S(iSVDremove),   'sr', 'markersize',2);
1594hold(Haxis(3), 'off');
1595ylabel(Haxis(3), 'Magnitude');
1596xlabel(Haxis(3), 'Singular Value Number');
1597axis(Haxis(3), 'tight');
1598a = axis(Haxis(3));
1599axis(Haxis(3), [0 length(S) a(3:4)]);
1600
1601drawnow;
1602
1603
1604
1605
1606
1607%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1608%  Post-correction display  %
1609%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1610function PostCorrectionDisplay(H, OCS0, OCS, Smat, S, U, V, Iteration, NumberOfTrys, MorePlotsFlag, InputFlags)
1611
1612ColorOrderMat = get(gca,'ColorOrder');
1613
1614% Build the orbit vectors
1615StartOrbitVec = [];
1616Orbit0Vec = [];
1617GoalOrbitVec = [];
1618OrbitNewVec = [];
1619%BPMWeight = [];
1620for i = 1:length(OCS.BPM)
1621    StartOrbitVec = [StartOrbitVec; OCS.BPM{i}.Data];
1622    Orbit0Vec     = [Orbit0Vec;     OCS.BPM{i}.Data];
1623    GoalOrbitVec  = [GoalOrbitVec;  OCS.GoalOrbit{i}];
1624
1625    %OCS.BPM{i} = getpv(OCS.BPM{i}, 'Struct', InputFlags{:});
1626    OrbitNewVec = [OrbitNewVec; OCS.BPM{i}.Data];
1627
1628    %if isempty(OCS.BPMWeight{i})
1629    %    BPMWeight = [BPMWeight; ones(length(OCS.BPM{i}.Data),1)];
1630    %else
1631    %    BPMWeight = [BPMWeight; OCS.BPMWeight{i}(:)];
1632    %end
1633end
1634
1635L = getfamilydata('Circumference');
1636if isempty(L)
1637    global THERING
1638    L = findspos(THERING, length(THERING)+1);
1639end
1640
1641
1642%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1643% Plot cumulative change in the corrector %
1644%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1645set(H(1), 'YLimMode', 'Auto');
1646hline = get(H(1), 'Children');
1647for i = 1:length(OCS.CM)
1648    CMpos = getspos(OCS.CM{i});
1649    [CMpos, isort] = sort(CMpos);
1650    set(hline(end-i+1), 'YData', OCS.CM{i}.Data(isort)-OCS0.CM{i}.Data(isort));
1651end
1652if length(OCS.CM) == 1
1653    set(get(H(1),'YLabel'), 'String', sprintf('\\Delta %s [%s]', OCS.CM{1}.FamilyName, OCS.CM{1}.UnitsString));
1654else
1655    set(get(H(1),'YLabel'), 'String', '\Delta Corrector');
1656end
1657
1658if NumberOfTrys == 1
1659    if OCS.FitRF
1660        DeltaRF = OCS.RF.Data - OCS0.RF.Data;
1661        TitleString = {sprintf('\\DeltaRF = %g %s   SV[%d out of %d]', DeltaRF, OCS.RF.UnitsString, max(OCS.SVDIndex), length(S)), 'Post-Orbit Correction'};
1662    else
1663        TitleString = {sprintf('SV[%d out of %d]', max(OCS.SVDIndex), length(S)), 'Post-Orbit Correction'};
1664    end
1665else
1666    if OCS.FitRF
1667        DeltaRF = OCS.RF.Data - OCS0.RF.Data;
1668        TitleString = {...
1669            sprintf('\\DeltaRF = %g %s    SV[%d out of %d]', DeltaRF, OCS.RF.UnitsString, max(OCS.SVDIndex), length(S)), ...
1670            sprintf('Iteration %d of %d', Iteration, NumberOfTrys)};
1671    else
1672        TitleString = {...
1673            sprintf('SV[%d out of %d]', max(OCS.SVDIndex), length(S)), ...
1674            sprintf('Iteration %d of %d', Iteration, NumberOfTrys)};
1675    end
1676end
1677set(get(H(1),'Title'), 'String', TitleString);
1678
1679%set(gca,'XTickLabel','');
1680
1681
1682
1683%%%%%%%%%%%%%%%%%%%%
1684% Plot Orbit Error %
1685%%%%%%%%%%%%%%%%%%%%
1686set(H(3), 'YLimMode', 'Auto');
1687hline = get(H(3), 'Children');
1688for i = 1:length(OCS.BPM)
1689    BPMpos = getspos(OCS.BPM{i});
1690    [BPMpos,isort] = sort(BPMpos);
1691    %plot(BPMpos, OCS.BPM{i}.Data(isort)-OCS.GoalOrbit{i}(isort),'.-','Color', ColorOrderMat(mod(i,size(ColorOrderMat,1)),:));
1692    set(hline(end-i+1), 'YData', OCS.BPM{i}.Data(isort)-OCS.GoalOrbit{i}(isort));
1693end
1694if length(OCS.BPM) == 1
1695    set(get(H(3),'YLabel'), 'String', sprintf('%s Remaining Error [%s]', OCS.BPM{1}.FamilyName, OCS.BPM{1}.UnitsString));
1696else
1697    set(get(H(3),'YLabel'), 'String', 'Remaining Orbit Error');
1698end
1699
1700
1701% if OCS.FitRF
1702%     set(OCS.Handles.RF, 'String', sprintf(' RF frequency was changed by  %g %s', OCS.DeltaRF, OCS.RF.UnitsString));
1703% end
1704
1705
1706drawnow;
1707
1708
1709
1710
1711
1712% % Plot Orbit Error
1713%
1714% The problem here is the orbit gets updated but .PredictedOrbitDelta does not
1715%
1716% axes(H(3));
1717%
1718% ColorOrderMat = get(gca,'ColorOrder');
1719% for i = 1:length(OCS.BPM)
1720%     BPMpos = getspos(OCS.BPM{i});
1721%     [BPMpos, isort] = sort(BPMpos);
1722%
1723%     % S-mat prediction: OrbitDelta + Error
1724%     plot(BPMpos, OCS.BPM{i}.PredictedOrbitDelta(isort) + (OCS.BPM{i}.Data(isort)-OCS.GoalOrbit{i}(isort)),'.-','Color', ColorOrderMat(mod(i,size(ColorOrderMat,1)),:));
1725%     hold on;
1726%     LabelCell2{i} = sprintf('%s [%s]', OCS.BPM{i}.FamilyName, OCS.BPM{i}.UnitsString);
1727% end
1728% hold off
1729% if length(LabelCell2) == 1
1730%     ylabel(sprintf('%s Residual [%s]', OCS.BPM{1}.FamilyName, OCS.BPM{1}.UnitsString));
1731% else
1732%     ylabel('Orbit Residual');
1733%     h_legend = legend(LabelCell2, 0);
1734%     set(h_legend, 'FontSize', 8);
1735% end
1736% title('Predicted Orbit Residual (by the Response Matrix)');
1737% xlabel('Position [Meters]');
1738% xaxis([0 L]);
1739% set(gca,'XTickLabel','');
1740
1741
1742
1743% %%%%%%%%%%%%%%%%%%%%%%
1744% % Predicted Residual %
1745% %%%%%%%%%%%%%%%%%%%%%%
1746% if length(H) < 3
1747%     figure(H(1));
1748%     subplot(3,1,3);
1749% else
1750%     axes(H(3));
1751% end
1752% for i = 1:length(OCS.BPM)
1753%     BPMpos = getspos(OCS.BPM{i});
1754%     [BPMpos, isort] = sort(BPMpos);
1755%
1756%     % S-mat prediction: OrbitDelta + Error
1757%     plot(BPMpos, OCS.BPM{i}.PredictedOrbitDelta(isort) + (OCS.BPM{i}.Data(isort)-OCS.GoalOrbit{i}(isort)),'.-','Color', ColorOrderMat(mod(i,size(ColorOrderMat,1)),:));
1758%     hold on;
1759%     LabelCell2{i} = sprintf('%s [%s]', OCS.BPM{i}.FamilyName, OCS.BPM{i}.UnitsString);
1760% end
1761% hold off
1762% if length(LabelCell2) == 1
1763%     ylabel(sprintf('%s Residual [%s]', OCS.BPM{1}.FamilyName, OCS.BPM{1}.UnitsString));
1764% else
1765%     ylabel('Orbit Residual');
1766%     h_legend = legend(LabelCell2, 0);
1767%     set(h_legend, 'FontSize', 8);
1768% end
1769% %title('Predicted Orbit Residual (by the Response Matrix)');
1770% xlabel('Position [Meters]');
1771% xaxis([0 L]);
1772
1773
1774
1775% for i = 1:length(OCS.BPM)
1776%     BPMpos = getspos(OCS.BPM{i});
1777%     [BPMpos,isort] = sort(BPMpos);
1778%
1779%     % S-mat prediction
1780%     plot(BPMpos, (OCS0.BPM{i}.Data(isort)-OCS.GoalOrbit{i}(isort)) + (OCS.BPM{i}.PredictedOrbitDelta(isort)),'.-','Color', ColorOrderMat(mod(i,size(ColorOrderMat,1)),:));
1781%     hold on;
1782%     LabelCell2{i} = sprintf('%s [%s]', OCS.BPM{i}.FamilyName, OCS.BPM{i}.UnitsString);
1783% end
1784% hold off
1785% if length(LabelCell2) == 1
1786%     ylabel(sprintf('%s Residual [%s]', OCS.BPM{1}.FamilyName, OCS.BPM{1}.UnitsString));
1787% else
1788%     ylabel('Orbit Residual');
1789%     h_legend = legend(LabelCell2, 0);
1790%     set(h_legend, 'FontSize', 8);
1791% end
1792% title('Predicted Orbit Residual (by the Response Matrix)');
1793% xlabel('Position [Meters]');
1794% xaxis([0 L]);
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807%     %%%%%%%%%%%%%%%%%%%%%
1808%     % Model predictions %
1809%     %%%%%%%%%%%%%%%%%%%%%
1810%     % %[Orbit0ModelX, Orbit0ModelY, Xpos, Ypos] = modeltwiss('x', 'All');
1811%     % for i = 1:length(OCS.BPM)
1812%     %     OCS0Model.BPM{i} = getpv(OCS.BPM{i},'Model');
1813%     % end
1814%     %
1815%     % % Step the model
1816%     % for i = 1:length(OCS.CM)
1817%     %     steppv(OCS.CM{i}.FamilyName, OCS.CM{i}.Field, OCS.CM{i}.Delta, OCS.CM{i}.DeviceList, 'Model', InputFlags{:});
1818%     % end
1819%     % if OCS.FitRF
1820%     %     stepsp('RF', OCS.DeltaRF, 'Model');
1821%     % end
1822%     %
1823%     % %[OrbitModelX, OrbitModelY] = modeltwiss('x', 'All');
1824%     % for i = 1:length(OCS.BPM)
1825%     %     OCSModel.BPM{i} = getpv(OCS.BPM{i},'Model');
1826%     % end
1827%     %
1828%     % % Step the model back
1829%     % for i = 1:length(OCS.CM)
1830%     %     steppv(OCS.CM{i}.FamilyName, OCS.CM{i}.Field, -1*OCS.CM{i}.Delta, OCS.CM{i}.DeviceList, 'Model', InputFlags{:});
1831%     % end
1832%     % if OCS.FitRF
1833%     %     stepsp('RF', -OCS.DeltaRF, 'Model');
1834%     % end
1835%     %
1836%     %
1837%     % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1838%     % % Plot Orbit Residue based on the AT model %
1839%     % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1840%     % axes(Haxis(7));
1841%     % ColorOrderMat = get(gca,'ColorOrder');
1842%     % for i = 1:length(OCS.BPM)
1843%     %     BPMpos = getspos(OCS.BPM{i});
1844%     %     [BPMpos,isort] = sort(BPMpos);
1845%     %
1846%     %     % Model prediction Error
1847%     %     plot(BPMpos, (OCSModel.BPM{i}.Data(isort)-OCS0Model.BPM{i}.Data(isort)) - (OCS.GoalOrbit{i}(isort)-OCS.BPM{i}.Data(isort)),'.-','Color', ColorOrderMat(mod(i,size(ColorOrderMat,1)),:));
1848%     %
1849%     %     % S-mat prediction
1850%     %     %    plot(BPMpos, (OCS0.BPM{i}.Data-OCS.GoalOrbit{i}) + (BPMSVDDeltaCell{i}),':','Color', ColorOrderMat(mod(i,size(ColorOrderMat,1)),:));
1851%     %     hold on;
1852%     %     LabelCell2{i} = sprintf('%s [%s]', OCS.BPM{i}.FamilyName, OCS.BPM{i}.UnitsString);
1853%     % end
1854%     % hold off
1855%     % if length(LabelCell2) == 1
1856%     %     ylabel(sprintf('%s Residual [%s]', OCS.BPM{1}.FamilyName, OCS.BPM{1}.UnitsString));
1857%     % else
1858%     %     ylabel('Orbit Residual');
1859%     %     h_legend = legend(LabelCell2, 0);
1860%     %     set(h_legend, 'FontSize', 8);
1861%     % end
1862%     % title('Predicted Orbit Residual (by the Nonlinear AT Model)');
1863%     % xlabel('Position [Meters]');
1864%     % xaxis([0 L]);
1865%     %
1866%     %
1867%     % % Linearization Error
1868%     % if length(H) < 4
1869%     %     figure(H(2));
1870%     %     subplot(4,1,4);
1871%     % else
1872%     %     axes(H(8));
1873%     % end
1874%     % ColorOrderMat = get(gca,'ColorOrder');
1875%     % for i = 1:length(OCS.BPM)
1876%     %     BPMpos = getspos(OCS.BPM{i});
1877%     %     [BPMpos,isort] = sort(BPMpos);
1878%     %
1879%     %     % Model - S-matrix prediction
1880%     %     plot(BPMpos, (OCSModel.BPM{i}.Data(isort)-OCS0Model.BPM{i}.Data(isort)) - OCS.BPM{i}.PredictedOrbitDelta(isort),'.-','Color', ColorOrderMat(mod(i,size(ColorOrderMat,1)),:));
1881%     %     hold on;
1882%     %     LabelCell2{i} = sprintf('%s [%s]', OCS.BPM{i}.FamilyName, OCS.BPM{i}.UnitsString);
1883%     % end
1884%     % hold off
1885%     % if length(LabelCell2) == 1
1886%     %     %ylabel(sprintf('%s Linearization Error [%s]', OCS.BPM{1}.FamilyName, OCS.BPM{1}.UnitsString));
1887%     %     ylabel(sprintf('Linearization Error [%s]', OCS.BPM{1}.UnitsString));
1888%     % else
1889%     %     ylabel('Linearization Error');
1890%     %     h_legend = legend(LabelCell2, 0);
1891%     %     set(h_legend, 'FontSize', 8);
1892%     % end
1893%     % title('Predicted Orbit Change Error (AT Model - Response Matrix)');
1894%     % xlabel('Position [Meters]');
1895%     % xaxis([0 L]);
Note: See TracBrowser for help on using the repository browser.