1 | function [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 |
---|
167 | ErrorFlag = 0; |
---|
168 | ExtraDelay = 0; |
---|
169 | DCCTLOW = .1; % A minimum stored current into the machine |
---|
170 | |
---|
171 | DefaultNIter = 1; |
---|
172 | DefaultSVDIndex = 1e-4; |
---|
173 | DefaultGoalOrbit = 'Golden'; |
---|
174 | DefaultFitRF = 0; |
---|
175 | DefaultDisplay = 0; |
---|
176 | DefaultCorrectorGain = 1; |
---|
177 | |
---|
178 | RespFlag = 'GoldenResp'; |
---|
179 | DispFlag = 'GoldenDisp'; |
---|
180 | SetSPFlag = 1; |
---|
181 | GetPVFlag = 1; |
---|
182 | RF0 = []; |
---|
183 | RF = []; |
---|
184 | FigHandles = []; |
---|
185 | AxesHandles = []; |
---|
186 | |
---|
187 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
188 | % Input parsing and checking % |
---|
189 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
190 | IncrementalFlag = -1; |
---|
191 | ModeFlag = ''; |
---|
192 | InputFlags = {}; |
---|
193 | OCSFlags = {}; |
---|
194 | |
---|
195 | % OCS init and defaults |
---|
196 | OCS.BPM = []; |
---|
197 | OCS.CM = []; |
---|
198 | OCS.GoalOrbit = DefaultGoalOrbit; |
---|
199 | OCS.SVDIndex = DefaultSVDIndex; |
---|
200 | OCS.FitRF = DefaultFitRF; |
---|
201 | OCS.NIter = DefaultNIter; |
---|
202 | OCS.Display = DefaultDisplay; |
---|
203 | OCS.CorrectorGain = DefaultCorrectorGain; |
---|
204 | OCS.Incremental = 0; |
---|
205 | OCS.Tolerance = 0; |
---|
206 | OCS.RampSteps = 1; |
---|
207 | |
---|
208 | % First check if an OCS structure was input |
---|
209 | OCSInputFlag = 0; |
---|
210 | if 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 |
---|
230 | end |
---|
231 | |
---|
232 | |
---|
233 | for 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 |
---|
376 | end |
---|
377 | |
---|
378 | OCSFlags = [OCSFlags {RespFlag} {DispFlag}]; |
---|
379 | |
---|
380 | |
---|
381 | if ~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 |
---|
480 | end |
---|
481 | |
---|
482 | |
---|
483 | % Get NIter |
---|
484 | if length(varargin) >= 1 |
---|
485 | OCS.NIter = varargin{1}; |
---|
486 | varargin(1) = []; |
---|
487 | end |
---|
488 | if isempty(OCS.NIter) |
---|
489 | OCS.NIter = DefaultNIter; |
---|
490 | end |
---|
491 | |
---|
492 | % Get SVDIndex |
---|
493 | if length(varargin) >= 1 |
---|
494 | OCS.SVDIndex = varargin{1}; |
---|
495 | varargin(1) = []; |
---|
496 | end |
---|
497 | if isempty(OCS.SVDIndex) |
---|
498 | OCS.SVDIndex = DefaultSVDIndex; |
---|
499 | end |
---|
500 | |
---|
501 | |
---|
502 | % Get BPMWeight |
---|
503 | if length(varargin) >= 1 |
---|
504 | OCS.BPMWeight = varargin{1}; |
---|
505 | varargin(1) = []; |
---|
506 | end |
---|
507 | |
---|
508 | |
---|
509 | % Check BPM field |
---|
510 | if isempty(OCS.BPM) |
---|
511 | OCS.BPM = {gethbpmfamily, getvbpmfamily}; |
---|
512 | end |
---|
513 | |
---|
514 | % Check CM field |
---|
515 | if isempty(OCS.CM) |
---|
516 | OCS.CM = {gethcmfamily, getvcmfamily}; |
---|
517 | end |
---|
518 | |
---|
519 | |
---|
520 | % Check the Display field |
---|
521 | if isempty(OCS.Display) |
---|
522 | OCS.Display = DefaultDisplay; |
---|
523 | end |
---|
524 | |
---|
525 | |
---|
526 | % Check the corrector gain |
---|
527 | if isempty(OCS.CorrectorGain) |
---|
528 | OCS.CorrectorGain = DefaultCorrectorGain; |
---|
529 | end |
---|
530 | |
---|
531 | |
---|
532 | % Check NIter |
---|
533 | if 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 |
---|
538 | else |
---|
539 | if OCS.NIter == 0 |
---|
540 | error('Number of iterations cannot be zero for absolute orbit changes'); |
---|
541 | end |
---|
542 | end |
---|
543 | |
---|
544 | |
---|
545 | % Make cell arrays if they are not already |
---|
546 | if ~iscell(OCS.BPM) |
---|
547 | NoCellBPMFlag = 1; |
---|
548 | OCS.BPM = {OCS.BPM}; |
---|
549 | else |
---|
550 | NoCellBPMFlag = 0; |
---|
551 | end |
---|
552 | if ~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 |
---|
558 | else |
---|
559 | NoCellCMFlag = 0; |
---|
560 | end |
---|
561 | |
---|
562 | |
---|
563 | % Attach the flags |
---|
564 | OCS.Flags = OCSFlags; |
---|
565 | |
---|
566 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
567 | % End input parsing and checking % |
---|
568 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
569 | |
---|
570 | |
---|
571 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
572 | % Check for good status if online % |
---|
573 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
574 | for 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 |
---|
587 | end |
---|
588 | for 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 |
---|
601 | end |
---|
602 | |
---|
603 | |
---|
604 | % Check BPMWeight |
---|
605 | if ~isfield(OCS, 'BPMWeight') |
---|
606 | for i = 1:length(OCS.BPM) |
---|
607 | OCS.BPMWeight{i} = []; |
---|
608 | end |
---|
609 | end |
---|
610 | if ~iscell(OCS.BPMWeight) |
---|
611 | OCS.BPMWeight = {OCS.BPMWeight}; |
---|
612 | end |
---|
613 | |
---|
614 | |
---|
615 | |
---|
616 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
617 | % Build the goal orbit cell % |
---|
618 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
619 | if 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 |
---|
632 | end |
---|
633 | if ~iscell(OCS.GoalOrbit) |
---|
634 | OCS.GoalOrbit = {OCS.GoalOrbit}; |
---|
635 | end |
---|
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 |
---|
647 | if OCS.FitRF ~= 0 && GetPVFlag |
---|
648 | OCS.RF = getrf('Struct', InputFlags{:}); |
---|
649 | end |
---|
650 | |
---|
651 | |
---|
652 | % Number of iterations (OCS.NIter can be 0 for display reasons with increment changes) |
---|
653 | if OCS.NIter == 0 |
---|
654 | NumberOfTrys = 1; |
---|
655 | else |
---|
656 | NumberOfTrys = OCS.NIter; |
---|
657 | end |
---|
658 | |
---|
659 | |
---|
660 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
661 | % Build the starting orbit % |
---|
662 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
663 | for 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 |
---|
673 | end |
---|
674 | |
---|
675 | % For increment changes, convert the goal orbit to an absolute orbit |
---|
676 | if 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; |
---|
683 | end |
---|
684 | |
---|
685 | |
---|
686 | |
---|
687 | % Interactively select singular value |
---|
688 | SVDquestion = 'Select Again'; |
---|
689 | MorePlotsFlag = 0; |
---|
690 | while 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 |
---|
828 | end |
---|
829 | |
---|
830 | |
---|
831 | %%%%%%%%%%%%%%%%%%%%%% |
---|
832 | % Exit if ~SetSPFlag % |
---|
833 | %%%%%%%%%%%%%%%%%%%%%% |
---|
834 | if ~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; |
---|
864 | end |
---|
865 | |
---|
866 | |
---|
867 | |
---|
868 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
869 | % Iterate on orbit correction % |
---|
870 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
871 | |
---|
872 | if ~isfield(OCS, 'MinimumPeriod') |
---|
873 | OCS.MinimumPeriod = 0; |
---|
874 | end |
---|
875 | if isempty(OCS.MinimumPeriod) |
---|
876 | OCS.MinimumPeriod = 0; |
---|
877 | end |
---|
878 | |
---|
879 | |
---|
880 | % Running flag |
---|
881 | RingSetOrbit.RunFlag = 1; |
---|
882 | setappdata(0, 'RingSetOrbit', RingSetOrbit); |
---|
883 | |
---|
884 | OCS.NCorrections = 0; |
---|
885 | for 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 |
---|
1067 | end |
---|
1068 | |
---|
1069 | |
---|
1070 | % Orbit correction finished |
---|
1071 | RingSetOrbit.RunFlag = 0; |
---|
1072 | setappdata(0, 'RingSetOrbit', RingSetOrbit); |
---|
1073 | |
---|
1074 | |
---|
1075 | % For multiple iterations put the total change in the .Delta & .DeltaRF fields |
---|
1076 | for i = 1:length(OCS.CM) |
---|
1077 | OCS.CM{i}.Delta = OCS.CM{i}.Data - OCS0.CM{i}.Data; |
---|
1078 | end |
---|
1079 | if OCS.FitRF |
---|
1080 | OCS.DeltaRF = OCS.RF.Data - OCS0.RF.Data; |
---|
1081 | end |
---|
1082 | |
---|
1083 | |
---|
1084 | % Remove the cell array if the input was not a cell |
---|
1085 | if 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}; |
---|
1094 | end |
---|
1095 | if 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 |
---|
1103 | end |
---|
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 | %%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
1120 | function [StopFlag, OCS, Smat, S, U, V, FigureHandles, MorePlotsFlag] = answersetorbitcall(OCS, Smat, S, U, V, FigureHandles, InputFlags) |
---|
1121 | |
---|
1122 | StopFlag = 0; |
---|
1123 | MorePlotsFlag = 0; |
---|
1124 | RingSetOrbit = getappdata(0, 'RingSetOrbit'); |
---|
1125 | |
---|
1126 | if ~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 | |
---|
1185 | end |
---|
1186 | |
---|
1187 | |
---|
1188 | |
---|
1189 | %%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
1190 | % Pre-correction display % |
---|
1191 | %%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
1192 | function [H, Haxis, OCS] = PreCorrectionDisplay(H, OCS0, OCS, Smat, S, U, V, NumberOfTrys, MorePlotsFlag, InputFlags) |
---|
1193 | |
---|
1194 | % Build the orbit vector |
---|
1195 | StartOrbitVec = []; |
---|
1196 | Orbit0Vec = []; |
---|
1197 | GoalOrbitVec = []; |
---|
1198 | BPMWeight = []; |
---|
1199 | for 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 |
---|
1209 | end |
---|
1210 | |
---|
1211 | % Plot some stuff |
---|
1212 | L = getfamilydata('Circumference'); |
---|
1213 | if isempty(L) |
---|
1214 | global THERING |
---|
1215 | L = findspos(THERING, length(THERING)+1); |
---|
1216 | end |
---|
1217 | |
---|
1218 | |
---|
1219 | if 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)]); |
---|
1234 | end |
---|
1235 | |
---|
1236 | |
---|
1237 | if 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 |
---|
1245 | else |
---|
1246 | Haxis = H; |
---|
1247 | end |
---|
1248 | |
---|
1249 | |
---|
1250 | ColorOrderMat = get(gca,'ColorOrder'); |
---|
1251 | |
---|
1252 | |
---|
1253 | %%%%%%%%%%%%%%%%%%%%%%% |
---|
1254 | % Change in corrector % |
---|
1255 | %%%%%%%%%%%%%%%%%%%%%%% |
---|
1256 | axes(Haxis(1)); |
---|
1257 | for 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; |
---|
1271 | end |
---|
1272 | hold off; |
---|
1273 | if 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)); |
---|
1276 | else |
---|
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'); |
---|
1282 | end |
---|
1283 | |
---|
1284 | %if NumberOfTrys == 1 |
---|
1285 | if 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'}); |
---|
1287 | else |
---|
1288 | title({sprintf('SV[%d out of %d]', max(OCS.SVDIndex), length(S)), 'Pre-Orbit Correction'}); |
---|
1289 | end |
---|
1290 | |
---|
1291 | %xlabel('Position [Meters]'); |
---|
1292 | xaxis([0 L]); |
---|
1293 | %set(gca,'XTickLabel',''); |
---|
1294 | |
---|
1295 | |
---|
1296 | |
---|
1297 | %%%%%%%%%%%%%%%%%%%% |
---|
1298 | % Plot Orbit Error % |
---|
1299 | %%%%%%%%%%%%%%%%%%%% |
---|
1300 | axes(Haxis(2)); |
---|
1301 | for 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); |
---|
1307 | end |
---|
1308 | hold off |
---|
1309 | if length(LabelCell2) == 1 |
---|
1310 | ylabel(sprintf('%s Starting Error [%s]', OCS.BPM{1}.FamilyName, OCS.BPM{1}.UnitsString)); |
---|
1311 | else |
---|
1312 | ylabel('Starting Orbit Error'); |
---|
1313 | h_legend = legend(LabelCell2, 0); |
---|
1314 | set(h_legend, 'FontSize', 8); |
---|
1315 | set(h_legend, 'UserData', 'Axes2'); |
---|
1316 | end |
---|
1317 | %title(sprintf('Orbit Error Before Correction (Iteration 1 of %d)', NumberOfTrys)); |
---|
1318 | %xlabel('Position [Meters]'); |
---|
1319 | xaxis([0 L]); |
---|
1320 | %set(gca,'XTickLabel',''); |
---|
1321 | |
---|
1322 | |
---|
1323 | |
---|
1324 | %%%%%%%%%%%%%%%%%%%%%% |
---|
1325 | % Predicted Residual % |
---|
1326 | %%%%%%%%%%%%%%%%%%%%%% |
---|
1327 | axes(Haxis(3)); |
---|
1328 | |
---|
1329 | for 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); |
---|
1337 | end |
---|
1338 | hold off |
---|
1339 | if length(LabelCell2) == 1 |
---|
1340 | ylabel(sprintf('%s Residual [%s]', OCS.BPM{1}.FamilyName, OCS.BPM{1}.UnitsString)); |
---|
1341 | else |
---|
1342 | ylabel('Orbit Residual'); |
---|
1343 | h_legend = legend(LabelCell2, 0); |
---|
1344 | set(h_legend, 'FontSize', 8); |
---|
1345 | set(h_legend, 'UserData', 'Axes3'); |
---|
1346 | end |
---|
1347 | %title('Predicted Orbit Residual (by the Response Matrix)'); |
---|
1348 | xlabel('Position [Meters]'); |
---|
1349 | xaxis([0 L]); |
---|
1350 | |
---|
1351 | |
---|
1352 | % Add TimeStamp labels |
---|
1353 | if 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 |
---|
1359 | end |
---|
1360 | |
---|
1361 | |
---|
1362 | |
---|
1363 | |
---|
1364 | if 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); |
---|
1394 | end |
---|
1395 | |
---|
1396 | drawnow; |
---|
1397 | |
---|
1398 | |
---|
1399 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
1400 | % End pre-correction display % |
---|
1401 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
1402 | |
---|
1403 | |
---|
1404 | |
---|
1405 | |
---|
1406 | function 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 |
---|
1434 | hbar = waitbar(0, 'Computing Orbit Change vs SVD#. Please wait ...'); |
---|
1435 | warning off; |
---|
1436 | LastGoodSvalue = 1; |
---|
1437 | OCStmp = OCS; |
---|
1438 | N = length(S); |
---|
1439 | for 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 |
---|
1469 | end |
---|
1470 | try |
---|
1471 | close(hbar); |
---|
1472 | catch |
---|
1473 | end |
---|
1474 | |
---|
1475 | |
---|
1476 | warning on; |
---|
1477 | if LastGoodSvalue ~= length(S) |
---|
1478 | fprintf(' Computational warning for choosing singular values above %d. \n', LastGoodSvalue); |
---|
1479 | end |
---|
1480 | |
---|
1481 | |
---|
1482 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
1483 | % CM strength vs SVD number % |
---|
1484 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
1485 | iSVDremove = 1:length(S); |
---|
1486 | [tmp1, tmp2, i] = intersect(OCS.SVDIndex, iSVDremove); |
---|
1487 | iSVDremove(i) = []; |
---|
1488 | |
---|
1489 | for i = 1:length(OCS.CM) |
---|
1490 | LabelCellCM{i} = sprintf('%s [%s]', OCS.CM{i}.FamilyName, OCS.CM{i}.UnitsString); |
---|
1491 | end |
---|
1492 | if 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 |
---|
1527 | else |
---|
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',''); |
---|
1550 | end |
---|
1551 | |
---|
1552 | |
---|
1553 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
1554 | % Plot Orbit Error vs SVD Number % |
---|
1555 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
1556 | %axes(Haxis(2)); |
---|
1557 | ColorOrderMat = get(Haxis(2),'ColorOrder'); |
---|
1558 | for 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); |
---|
1567 | end |
---|
1568 | hold(Haxis(2), 'off'); |
---|
1569 | if length(LabelCell2) == 1 |
---|
1570 | ylabel(Haxis(2), sprintf('STD %s [%s]', OCS.BPM{1}.FamilyName, OCS.BPM{1}.UnitsString)); |
---|
1571 | else |
---|
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'); |
---|
1576 | end |
---|
1577 | %title(Haxis(2), 'Standard Deviation of the Predicted Orbit Residual'); |
---|
1578 | %xlabel(Haxis(2), 'Singular Value Number'); |
---|
1579 | |
---|
1580 | axis(Haxis(2), 'tight'); |
---|
1581 | a = axis(Haxis(2)); |
---|
1582 | axis(Haxis(2), [0 length(S) a(3:4)]); |
---|
1583 | %set(gca,'XTickLabel',''); |
---|
1584 | |
---|
1585 | |
---|
1586 | %%%%%%%%%%%%%%%%%%%%%%%% |
---|
1587 | % Plot singular values % |
---|
1588 | %%%%%%%%%%%%%%%%%%%%%%%% |
---|
1589 | axes(Haxis(3)); |
---|
1590 | semilogy(Haxis(3), S, '-b'); |
---|
1591 | hold(Haxis(3), 'on'); |
---|
1592 | semilogy(Haxis(3), OCS.SVDIndex, S(OCS.SVDIndex), 'sb', 'markersize',2); |
---|
1593 | semilogy(Haxis(3), iSVDremove, S(iSVDremove), 'sr', 'markersize',2); |
---|
1594 | hold(Haxis(3), 'off'); |
---|
1595 | ylabel(Haxis(3), 'Magnitude'); |
---|
1596 | xlabel(Haxis(3), 'Singular Value Number'); |
---|
1597 | axis(Haxis(3), 'tight'); |
---|
1598 | a = axis(Haxis(3)); |
---|
1599 | axis(Haxis(3), [0 length(S) a(3:4)]); |
---|
1600 | |
---|
1601 | drawnow; |
---|
1602 | |
---|
1603 | |
---|
1604 | |
---|
1605 | |
---|
1606 | |
---|
1607 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
1608 | % Post-correction display % |
---|
1609 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
1610 | function PostCorrectionDisplay(H, OCS0, OCS, Smat, S, U, V, Iteration, NumberOfTrys, MorePlotsFlag, InputFlags) |
---|
1611 | |
---|
1612 | ColorOrderMat = get(gca,'ColorOrder'); |
---|
1613 | |
---|
1614 | % Build the orbit vectors |
---|
1615 | StartOrbitVec = []; |
---|
1616 | Orbit0Vec = []; |
---|
1617 | GoalOrbitVec = []; |
---|
1618 | OrbitNewVec = []; |
---|
1619 | %BPMWeight = []; |
---|
1620 | for 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 |
---|
1633 | end |
---|
1634 | |
---|
1635 | L = getfamilydata('Circumference'); |
---|
1636 | if isempty(L) |
---|
1637 | global THERING |
---|
1638 | L = findspos(THERING, length(THERING)+1); |
---|
1639 | end |
---|
1640 | |
---|
1641 | |
---|
1642 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
1643 | % Plot cumulative change in the corrector % |
---|
1644 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
1645 | set(H(1), 'YLimMode', 'Auto'); |
---|
1646 | hline = get(H(1), 'Children'); |
---|
1647 | for 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)); |
---|
1651 | end |
---|
1652 | if length(OCS.CM) == 1 |
---|
1653 | set(get(H(1),'YLabel'), 'String', sprintf('\\Delta %s [%s]', OCS.CM{1}.FamilyName, OCS.CM{1}.UnitsString)); |
---|
1654 | else |
---|
1655 | set(get(H(1),'YLabel'), 'String', '\Delta Corrector'); |
---|
1656 | end |
---|
1657 | |
---|
1658 | if 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 |
---|
1665 | else |
---|
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 |
---|
1676 | end |
---|
1677 | set(get(H(1),'Title'), 'String', TitleString); |
---|
1678 | |
---|
1679 | %set(gca,'XTickLabel',''); |
---|
1680 | |
---|
1681 | |
---|
1682 | |
---|
1683 | %%%%%%%%%%%%%%%%%%%% |
---|
1684 | % Plot Orbit Error % |
---|
1685 | %%%%%%%%%%%%%%%%%%%% |
---|
1686 | set(H(3), 'YLimMode', 'Auto'); |
---|
1687 | hline = get(H(3), 'Children'); |
---|
1688 | for 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)); |
---|
1693 | end |
---|
1694 | if length(OCS.BPM) == 1 |
---|
1695 | set(get(H(3),'YLabel'), 'String', sprintf('%s Remaining Error [%s]', OCS.BPM{1}.FamilyName, OCS.BPM{1}.UnitsString)); |
---|
1696 | else |
---|
1697 | set(get(H(3),'YLabel'), 'String', 'Remaining Orbit Error'); |
---|
1698 | end |
---|
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 | |
---|
1706 | drawnow; |
---|
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]); |
---|