1 | function S = measrespmat(varargin) |
---|
2 | %MEASRESPMAT - Measure a response matrix |
---|
3 | % |
---|
4 | % For family name, device list inputs: |
---|
5 | % S = measrespmat(MonitorFamily, MonitorDeviceList, ActuatorFamily, ActuatorDeviceList, ActuatorDelta, ModulationMethod, WaitFlag, ExtraDelay) |
---|
6 | % |
---|
7 | % For data structure inputs: |
---|
8 | % S = measrespmat(MonitorStruct, ActuatorStruct, ActuatorDelta, ModulationMethod, WaitFlag, ExtraDelay) |
---|
9 | % |
---|
10 | % INPUTS |
---|
11 | % 1. MonitorFamily - AcceleratorObjects family name for monitors |
---|
12 | % MonitorDeviceList - AcceleratorObjects device list for monitors (element or device) |
---|
13 | % (MonitorFamily and MonitorDeviceList can be cell arrays) |
---|
14 | % or |
---|
15 | % MonitorStruct can replace MonitorFamily and MonitorDeviceList |
---|
16 | % |
---|
17 | % 2. ActuatorFamily - AcceleratorObjects family name for actuators |
---|
18 | % ActuatorDeviceList - AcceleratorObjects device list for actuators (element or device) |
---|
19 | % or |
---|
20 | % ActuatorStruct can replace ActuatorFamily and ActuatorDeviceList |
---|
21 | % |
---|
22 | % 3. ActuatorDelta - Change in actuator {Default: getfamilydata('ActuatorFamily','Setpoint','DeltaRespMat')} |
---|
23 | % 4. ModulationMethod - Method for changing the ActuatorFamily |
---|
24 | % 'bipolar' changes the ActuatorFamily by +/- ActuatorDelta/2 on each step {Default} |
---|
25 | % 'unipolar' changes the ActuatorFamily from 0 to ActuatorDelta on each step |
---|
26 | % 5. WaitFlag - (see setpv for WaitFlag definitions) {Default: []} |
---|
27 | % WaitFlag = -5 will override gets to manual mode |
---|
28 | % |
---|
29 | % 6. ExtraDelay - Extra time delay [seconds] after a setpoint change |
---|
30 | % |
---|
31 | % 7. 'Struct' - Output will be a response matrix structure {Default for data structure inputs} |
---|
32 | % 'Numeric' - Output will be a numeric matrix {Default for non-data structure inputs} |
---|
33 | % |
---|
34 | % 8. Optional override of the units: |
---|
35 | % 'Physics' - Use physics units |
---|
36 | % 'Hardware' - Use hardware units |
---|
37 | % |
---|
38 | % 9. Optional override of the mode: |
---|
39 | % 'Online' - Set/Get data online |
---|
40 | % 'Model' - Set/Get data on the model (same as 'Simulator') |
---|
41 | % 'Manual' - Set/Get data manually |
---|
42 | % |
---|
43 | % 10. 'Display' - Prints status information to the command window {Default} |
---|
44 | % 'NoDisplay' - Nothing is printed to the command window |
---|
45 | % |
---|
46 | % 11. 'MinimumBeamCurrent' - Minimum beam current before prompting for a refill |
---|
47 | % The current (as returned by getdcct) must follow the flag. |
---|
48 | % measbpmresp('MinimumBeamCurrent', 32.1) |
---|
49 | % will pause at a beam current of 32.1 and prompt for a refill. |
---|
50 | % |
---|
51 | % OUTPUTS |
---|
52 | % 1. S = Response matrix |
---|
53 | % |
---|
54 | % For stucture outputs: |
---|
55 | % S(Monitor, Actuator).Data - Response matrix |
---|
56 | % .Monitor - Monitor data structure (starting orbit) |
---|
57 | % .Monitor1 - First data point matrix |
---|
58 | % .Monitor2 - Second data point matrix |
---|
59 | % .Actuator - Corrector data structure |
---|
60 | % .ActuatorDelta - Corrector kick vector |
---|
61 | % .GeV - Electron beam energy |
---|
62 | % .ModulationMethod - 'unipolar' or 'bipolar' |
---|
63 | % .WaitFlag - Wait flag used when acquiring data |
---|
64 | % .ExtraDelay - Extra time delay |
---|
65 | % .TimeStamp - Matlab clock at the start of each actuator family |
---|
66 | % .CreatedBy |
---|
67 | % .DCCT |
---|
68 | % |
---|
69 | % NOTES |
---|
70 | % 1. If MonitorFamily and MonitorDeviceList are cell arrays, then S is a cell array of response matrices. |
---|
71 | % 2. ActuatorFamily, ActuatorDeviceList, ActuatorDelta, ModulationMethod, WaitFlag are not cell arrrays. |
---|
72 | % 3. If ActuatorDeviceList is empty, then the entire family is change together. |
---|
73 | % 4. Bipolar mode changes the actuator by +/- ActuatorDelta/2 |
---|
74 | % 5. Unipolar mode changes the actuator by ActuatorDelta |
---|
75 | % 6. Return values are MonitorChange/ActuatorDelta (normalized) |
---|
76 | % 7. When using cell array inputs don't mix structure data inputs with non-structure data |
---|
77 | % |
---|
78 | % EXAMPLES |
---|
79 | % 1. 2x2 tune response matrix for Q7 and Q9 families (delay for tune matrix will need to be adjusted): |
---|
80 | % TuneRmatrix = [measrespmat('TUNE',[1;2],'Q7',[],.5,'unipolar') ... |
---|
81 | % measrespmat('TUNE',[1;2],'Q9',[],.5,'unipolar')]; |
---|
82 | % |
---|
83 | % 2. Orbit response matrix for all the horizontal correctors (+/-1 amp kick amplitude): |
---|
84 | % Smat = measrespmat({'BPMx','BPMz'}, {getlist('BPMx'),getlist('BPMz')}, 'HCOR', ... |
---|
85 | % getlist('HCOR'),1,'bipolar',-2); |
---|
86 | % The output is stored in a cell array. Smat{1} is the horizontal plane and Smat{2} is the vertical cross plane. |
---|
87 | % |
---|
88 | % 3. Orbit response matrix for all the horizontal correctors (Default kick amplitude): |
---|
89 | % Smat = measrespmat(getx('Struct'), getsp('HCOR','struct')); |
---|
90 | |
---|
91 | % |
---|
92 | % Written by Gregory J. Portmann |
---|
93 | % Modified By Laurent S. Nadolski |
---|
94 | |
---|
95 | % Initialize |
---|
96 | ActuatorDelta = []; |
---|
97 | ActuatorDeviceList = []; |
---|
98 | ModulationMethod = 'bipolar'; |
---|
99 | WaitFlag = []; |
---|
100 | WaitFlagMonitor = 0; |
---|
101 | ExtraDelay = 0; |
---|
102 | StructOutputFlag = 0; |
---|
103 | NumericOutputFlag = 0; |
---|
104 | DisplayFlag = 1; |
---|
105 | ModeFlagCell = {}; |
---|
106 | UnitsFlagCell = {}; |
---|
107 | DCCTStopFlag = 0; |
---|
108 | |
---|
109 | InputFlags = {}; |
---|
110 | for i = length(varargin):-1:1 |
---|
111 | if isstruct(varargin{i}) |
---|
112 | % Ignor structures |
---|
113 | elseif iscell(varargin{i}) |
---|
114 | % Ignor cells |
---|
115 | elseif strcmpi(varargin{i},'Struct') |
---|
116 | StructOutputFlag = 1; |
---|
117 | varargin(i) = []; |
---|
118 | elseif strcmpi(varargin{i},'Numeric') |
---|
119 | NumericOutputFlag = 1; |
---|
120 | StructOutputFlag = 0; |
---|
121 | varargin(i) = []; |
---|
122 | elseif strcmpi(varargin{i},'Simulator') || strcmpi(varargin{i},'Model') |
---|
123 | ModeFlagCell = varargin(i); |
---|
124 | InputFlags = [InputFlags varargin(i)]; |
---|
125 | varargin(i) = []; |
---|
126 | elseif strcmpi(varargin{i},'Online') |
---|
127 | ModeFlagCell = varargin(i); |
---|
128 | InputFlags = [InputFlags varargin(i)]; |
---|
129 | varargin(i) = []; |
---|
130 | elseif strcmpi(varargin{i},'Manual') |
---|
131 | ModeFlagCell = varargin(i); |
---|
132 | InputFlags = [InputFlags varargin(i)]; |
---|
133 | varargin(i) = []; |
---|
134 | elseif strcmpi(varargin{i},'Physics') |
---|
135 | UnitsFlagCell = varargin(i); |
---|
136 | InputFlags = [InputFlags varargin(i)]; |
---|
137 | varargin(i) = []; |
---|
138 | elseif strcmpi(varargin{i},'Hardware') |
---|
139 | UnitsFlagCell = varargin(i); |
---|
140 | InputFlags = [InputFlags varargin(i)]; |
---|
141 | varargin(i) = []; |
---|
142 | elseif strcmpi(varargin{i},'NoDisplay') |
---|
143 | DisplayFlag = 0; |
---|
144 | varargin(i) = []; |
---|
145 | elseif strcmpi(varargin{i},'Display') |
---|
146 | DisplayFlag = 1; |
---|
147 | varargin(i) = []; |
---|
148 | elseif strcmpi(varargin{i},'MinimumBeamCurrent') |
---|
149 | DCCTStopFlag = 1; |
---|
150 | DCCTStop = varargin{i+1}; |
---|
151 | varargin(i+1) = []; |
---|
152 | varargin(i) = []; |
---|
153 | end |
---|
154 | end |
---|
155 | |
---|
156 | |
---|
157 | if length(varargin) < 2 |
---|
158 | error('Not enough inputs') |
---|
159 | end |
---|
160 | |
---|
161 | |
---|
162 | |
---|
163 | % Find out if the inputs are data structures |
---|
164 | StructInputFlag = 0; |
---|
165 | if isstruct(varargin{1}) |
---|
166 | StructInputFlag = 1; |
---|
167 | elseif iscell(varargin{1}) |
---|
168 | if isstruct(varargin{1}{1}) |
---|
169 | StructInputFlag = 1; |
---|
170 | end |
---|
171 | end |
---|
172 | |
---|
173 | |
---|
174 | if StructInputFlag |
---|
175 | % S = measrespmat(MonitorStruct, ActuatorStruct, ActuatorDelta, ModulationMethod, WaitFlag, ExtraDelay) |
---|
176 | if length(varargin) < 2 |
---|
177 | error('At least 2 inputs required in structure mode.'); |
---|
178 | end |
---|
179 | |
---|
180 | % Only change StructOutputFlag if 'numeric' is not on the input line |
---|
181 | if ~NumericOutputFlag |
---|
182 | StructOutputFlag = 1; |
---|
183 | end |
---|
184 | |
---|
185 | MonitorStruct = varargin{1}; |
---|
186 | ActuatorStruct = varargin{2}; |
---|
187 | if ~isstruct(ActuatorStruct) |
---|
188 | error('If monitors are data structures, then the actuator must also be a data structure.'); |
---|
189 | end |
---|
190 | |
---|
191 | if iscell(varargin{1}) |
---|
192 | for j = 1:length(MonitorStruct) |
---|
193 | if ~isstruct(MonitorStruct{j}) |
---|
194 | error('All monitors in the cell must be data structures or not (mixing methods not allowed).'); |
---|
195 | end |
---|
196 | |
---|
197 | MonitorFamily{j} = MonitorStruct{j}.FamilyName; |
---|
198 | MonitorDeviceList{j} = MonitorStruct{j}.DeviceList; |
---|
199 | end |
---|
200 | else |
---|
201 | MonitorFamily = MonitorStruct.FamilyName; |
---|
202 | MonitorDeviceList = MonitorStruct.DeviceList; |
---|
203 | end |
---|
204 | ActuatorFamily = ActuatorStruct.FamilyName; |
---|
205 | ActuatorDeviceList = ActuatorStruct.DeviceList; |
---|
206 | if length(varargin) >= 3 |
---|
207 | ActuatorDelta = varargin{3}; |
---|
208 | end |
---|
209 | if length(varargin) >= 4 |
---|
210 | ModulationMethod = varargin{4}; |
---|
211 | end |
---|
212 | if length(varargin) >= 5 |
---|
213 | WaitFlag = varargin{5}; |
---|
214 | end |
---|
215 | if length(varargin) >= 6 |
---|
216 | ExtraDelay = varargin{6}; |
---|
217 | end |
---|
218 | else |
---|
219 | % S = measrespmat(MonitorFamily, MonitorDeviceList, ActuatorFamily, ActuatorDeviceList, ActuatorDelta, ModulationMethod, WaitFlag, ExtraDelay) |
---|
220 | if length(varargin) < 3 |
---|
221 | error('At least 3 inputs required '); |
---|
222 | end |
---|
223 | MonitorFamily = varargin{1}; |
---|
224 | MonitorDeviceList = varargin{2}; |
---|
225 | ActuatorFamily = varargin{3}; |
---|
226 | if length(varargin) >= 4 |
---|
227 | ActuatorDeviceList = varargin{4}; |
---|
228 | end |
---|
229 | if length(varargin) >= 5 |
---|
230 | ActuatorDelta = varargin{5}; |
---|
231 | end |
---|
232 | if length(varargin) >= 6 |
---|
233 | ModulationMethod = varargin{6}; |
---|
234 | end |
---|
235 | if length(varargin) >= 7 |
---|
236 | WaitFlag = varargin{7}; |
---|
237 | end |
---|
238 | if length(varargin) >= 8 |
---|
239 | ExtraDelay = varargin{8}; |
---|
240 | end |
---|
241 | end |
---|
242 | |
---|
243 | % Remove extra delay for model |
---|
244 | if any(strcmpi('Model', ModeFlagCell)) || any(strcmpi('Simulator', ModeFlagCell)) |
---|
245 | ExtraDelay = 0; |
---|
246 | end |
---|
247 | |
---|
248 | if isempty(ModulationMethod) |
---|
249 | ModulationMethod = 'bipolar'; |
---|
250 | elseif ~strcmpi(ModulationMethod, 'unipolar') && ~strcmpi(ModulationMethod, 'bipolar') |
---|
251 | error('ModulationMethod must be ''unipolar'' or ''bipolar'''); |
---|
252 | end |
---|
253 | |
---|
254 | |
---|
255 | % Force to be a cells of equal length |
---|
256 | if ~iscell(MonitorFamily) |
---|
257 | MonitorFamily = {MonitorFamily}; |
---|
258 | end |
---|
259 | if ~iscell(MonitorDeviceList) |
---|
260 | MonitorDeviceList = {MonitorDeviceList}; |
---|
261 | end |
---|
262 | if ~iscell(ActuatorFamily) |
---|
263 | ActuatorFamily = {ActuatorFamily}; |
---|
264 | end |
---|
265 | if isempty(ActuatorDeviceList) |
---|
266 | for i = 1:length(ActuatorFamily) |
---|
267 | ActuatorDeviceList{i} = []; |
---|
268 | end |
---|
269 | elseif ~iscell(ActuatorDeviceList) |
---|
270 | ActuatorDeviceList = {ActuatorDeviceList}; |
---|
271 | end |
---|
272 | if isempty(ActuatorDelta) |
---|
273 | for i = 1:length(ActuatorFamily) |
---|
274 | ActuatorDelta{i} = []; |
---|
275 | end |
---|
276 | elseif ~iscell(ActuatorDelta) |
---|
277 | ActuatorDelta = {ActuatorDelta}; |
---|
278 | end |
---|
279 | |
---|
280 | |
---|
281 | % Force column for monitors and rows for actuators |
---|
282 | MonitorFamily = MonitorFamily(:); |
---|
283 | MonitorDeviceList = MonitorDeviceList(:); |
---|
284 | ActuatorFamily = ActuatorFamily(:)'; |
---|
285 | ActuatorDeviceList = ActuatorDeviceList(:)'; |
---|
286 | ActuatorDelta = ActuatorDelta(:)'; |
---|
287 | |
---|
288 | |
---|
289 | % Check length of cell inputs |
---|
290 | if length(MonitorFamily) ~= length(MonitorDeviceList) |
---|
291 | error('The length of MonitorFamily (cell) must equal the length of MonitorDeviceList (cell)'); |
---|
292 | end |
---|
293 | if length(ActuatorFamily) ~= length(ActuatorDeviceList) |
---|
294 | error('The length of ActuatorFamily (cell) must equal the length of ActuatorDeviceList (cell)'); |
---|
295 | end |
---|
296 | if length(ActuatorFamily) ~= length(ActuatorDelta) |
---|
297 | error('The length of ActuatorFamily (cell) must equal the length of ActuatorDelta (cell)'); |
---|
298 | end |
---|
299 | |
---|
300 | |
---|
301 | % Manual mode for monitors |
---|
302 | WaitFlagMonitor = WaitFlag; |
---|
303 | if WaitFlag == -5 |
---|
304 | WaitFlag = 0; |
---|
305 | end |
---|
306 | |
---|
307 | |
---|
308 | % First get all defaults and do some error checking |
---|
309 | for iActFam = 1:length(ActuatorFamily) |
---|
310 | % Convert element list to a device list if necessary |
---|
311 | if size(ActuatorDeviceList{iActFam},2) == 1 |
---|
312 | ActuatorDeviceList{iActFam} = elem2dev(ActuatorFamily{iActFam}, ActuatorDeviceList{iActFam}); |
---|
313 | end |
---|
314 | |
---|
315 | % Get ActuatorDelta if empty |
---|
316 | if isempty(ActuatorDelta{iActFam}) |
---|
317 | % Find the delta from the AO (.DeltaRespMat is always hardware!!!) |
---|
318 | ActuatorDelta{iActFam} = getfamilydata(ActuatorFamily{iActFam}, 'Setpoint', 'DeltaRespMat', ActuatorDeviceList{iActFam}); |
---|
319 | if isempty(ActuatorDelta{iActFam}) |
---|
320 | error(sprintf('%s.Setpoint.DeltaRespMat field must be set properly',ActuatorFamily{iActFam})); |
---|
321 | end |
---|
322 | |
---|
323 | % Check if ActuatorDelta needs a units conversion |
---|
324 | if strcmpi(UnitsFlagCell,{'Physics'}) |
---|
325 | % Check over-ride |
---|
326 | ActuatorDelta{iActFam} = hw2physics(ActuatorFamily{iActFam}, 'Setpoint', ActuatorDelta{iActFam}, ActuatorDeviceList{iActFam}, ModeFlagCell{:}); |
---|
327 | else |
---|
328 | % Check family |
---|
329 | Units = getfamilydata(ActuatorFamily{iActFam}, 'Setpoint', 'Units'); |
---|
330 | if strcmpi(Units, 'Physics') |
---|
331 | ActuatorDelta{iActFam} = hw2physics(ActuatorFamily{iActFam}, 'Setpoint', ActuatorDelta{iActFam}, ActuatorDeviceList{iActFam}, ModeFlagCell{:}); |
---|
332 | end |
---|
333 | end |
---|
334 | %if strcmpi(UnitsFlagCell,{'Hardware'}) & strcmpi(Units, 'Physics') |
---|
335 | % ActuatorDelta{iActFam} = physics2hw(ActuatorFamily{iActFam}, 'Setpoint', ActuatorDelta{iActFam}, ActuatorDeviceList{iActFam}, ModeFlagCell{:}); |
---|
336 | %end |
---|
337 | end |
---|
338 | if isempty(ActuatorDelta{iActFam}) |
---|
339 | error('ActuatorDelta is empty. Must be an input or in the family structure (.DeltaRespMat in hardware units)'); |
---|
340 | end |
---|
341 | if ~isnumeric(ActuatorDelta{iActFam}) |
---|
342 | error('ActuatorDelta must be numeric.'); |
---|
343 | end |
---|
344 | |
---|
345 | % Force ActuatorDelta to be a column vector |
---|
346 | ActuatorDelta{iActFam} = ActuatorDelta{iActFam}(:); |
---|
347 | |
---|
348 | % Check for entire family |
---|
349 | if isempty(ActuatorDeviceList{iActFam}) |
---|
350 | % Set the entire family at once |
---|
351 | iActDeviceTotal{iActFam} = 1; |
---|
352 | |
---|
353 | % Expand a scalar to all devices |
---|
354 | if length(ActuatorDelta{iActFam}) == 1 |
---|
355 | % OK |
---|
356 | elseif length(ActuatorDelta{iActFam}) == length(family2dev(ActuatorFamily{iActFam})) |
---|
357 | % OK |
---|
358 | else |
---|
359 | error('ActuatorDelta must be a scalar or equal in length to the number of devices'); |
---|
360 | end |
---|
361 | else |
---|
362 | iActDeviceTotal{iActFam} = size(ActuatorDeviceList{iActFam},1); |
---|
363 | |
---|
364 | % Expand a scalar to all devices if scalar |
---|
365 | if length(ActuatorDelta{iActFam}) == 1 |
---|
366 | ActuatorDelta{iActFam} = ActuatorDelta{iActFam} * ones(iActDeviceTotal{iActFam},1); |
---|
367 | end |
---|
368 | % Size of ActuatorDelta must equal total number of devices |
---|
369 | if length(ActuatorDelta{iActFam}) ~= iActDeviceTotal{iActFam} |
---|
370 | error('ActuatorDelta must be a scalar or equal in length to the number of devices'); |
---|
371 | end |
---|
372 | end |
---|
373 | |
---|
374 | % Check for zeros |
---|
375 | if any(ActuatorDelta{iActFam} == 0) |
---|
376 | error('At least one the actuator deltas is zero.'); |
---|
377 | end |
---|
378 | |
---|
379 | % Get initial actuator values |
---|
380 | ActuatorStart{iActFam} = getsp(ActuatorFamily{iActFam}, ActuatorDeviceList{iActFam}, 'Struct', InputFlags{:}); |
---|
381 | InitActuator = ActuatorStart{iActFam}.Data; |
---|
382 | |
---|
383 | % Check actuator limits |
---|
384 | if strcmpi(ModulationMethod, 'unipolar') |
---|
385 | % unipolar measurement |
---|
386 | [LimitFlag, LimitList] = checklimits(ActuatorFamily{iActFam}, InitActuator+ActuatorDelta{iActFam}, ActuatorDeviceList{iActFam}, UnitsFlagCell{:}); |
---|
387 | if LimitFlag |
---|
388 | MagnetString = sprintf('%s(%d,%d)=%f, Delta=%f', ActuatorFamily{iActFam}, ActuatorDeviceList{iActFam}(LimitList(1),:), InitActuator(LimitList(1)), ActuatorDelta{iActFam}(LimitList(1))); |
---|
389 | error(['Actuator limit would be exceeded (Setpoint+Delta) (', MagnetString, ')']); |
---|
390 | end |
---|
391 | elseif strcmpi(ModulationMethod, 'bipolar') |
---|
392 | % bipolar measurement |
---|
393 | [LimitFlag, LimitList] = checklimits(ActuatorFamily{iActFam}, InitActuator-ActuatorDelta{iActFam}/2, ActuatorDeviceList{iActFam}, UnitsFlagCell{:}); |
---|
394 | if LimitFlag |
---|
395 | if isempty(ActuatorDeviceList{:}), ActuatorDeviceList{:} = [1 1]; end |
---|
396 | MagnetString = sprintf('%s(%d,%d)=%f, Delta=%f', ActuatorFamily{iActFam}, ActuatorDeviceList{iActFam}(LimitList(1),:), InitActuator(LimitList(1)), ActuatorDelta{iActFam}(LimitList(1))); |
---|
397 | error(['Actuator limit would be exceeded (Setpoint-Delta/2) (', MagnetString, ')']); |
---|
398 | end |
---|
399 | [LimitFlag, LimitList] = checklimits(ActuatorFamily{iActFam}, InitActuator+ActuatorDelta{iActFam}/2, ActuatorDeviceList{iActFam}, UnitsFlagCell{:}); |
---|
400 | if LimitFlag |
---|
401 | MagnetString = sprintf('%s(%d,%d)=%f, Delta=%f', ActuatorFamily{iActFam}, ActuatorDeviceList{iActFam}(LimitList(1),:), InitActuator(LimitList(1)), ActuatorDelta{iActFam}(LimitList(1))); |
---|
402 | error(['Actuator limit would be exceeded (Setpoint+Delta/2) (', MagnetString, ')']); |
---|
403 | end |
---|
404 | end |
---|
405 | end |
---|
406 | |
---|
407 | |
---|
408 | if DisplayFlag |
---|
409 | fprintf(' Measuring response using a %s actuator method\n', lower(ModulationMethod)); |
---|
410 | end |
---|
411 | |
---|
412 | % Begin main loop over actuators |
---|
413 | StopNow = 0; |
---|
414 | for iActFam = 1:length(ActuatorFamily) |
---|
415 | t0 = clock; |
---|
416 | clear R; |
---|
417 | |
---|
418 | % Get initial monitor values |
---|
419 | if StructOutputFlag |
---|
420 | if WaitFlagMonitor == -5 |
---|
421 | MonitorStart = getam(MonitorFamily, MonitorDeviceList, 'Struct', 'Manual', UnitsFlagCell{:}); |
---|
422 | else |
---|
423 | MonitorStart = getam(MonitorFamily, MonitorDeviceList, 'Struct', InputFlags{:}); |
---|
424 | end |
---|
425 | if isfamily('DCCT') |
---|
426 | DCCTStart = getdcct(ModeFlagCell{:}); |
---|
427 | else |
---|
428 | DCCTStart = NaN; |
---|
429 | end |
---|
430 | end |
---|
431 | |
---|
432 | % Get initial actuator values |
---|
433 | InitActuator = ActuatorStart{iActFam}.Data; |
---|
434 | |
---|
435 | % Just to display common names (empty if not using common names) |
---|
436 | CommonNameList = family2common(ActuatorFamily{iActFam}, ActuatorDeviceList{iActFam}); |
---|
437 | |
---|
438 | % Iterate on each actuator in the device list |
---|
439 | if DisplayFlag % & ~isempty(ActuatorDeviceList{iActFam}) %iActDeviceTotal{iActFam} > 1 |
---|
440 | fprintf('\n %s family response matrix\n', ActuatorFamily{iActFam}); |
---|
441 | end |
---|
442 | |
---|
443 | % Individual actuator loop |
---|
444 | for iActDevice = 1:iActDeviceTotal{iActFam} |
---|
445 | if ~isempty(CommonNameList) |
---|
446 | CommonName = [deblank(CommonNameList(iActDevice,:)), ' ']; |
---|
447 | if strcmpi(deblank(CommonName), ActuatorFamily{iActFam}) |
---|
448 | CommonName = ''; |
---|
449 | end |
---|
450 | end |
---|
451 | |
---|
452 | % Remove the CommonName for now |
---|
453 | CommonName = ''; |
---|
454 | |
---|
455 | % Step actuator down for bipolar |
---|
456 | try |
---|
457 | if strcmpi(ModulationMethod, 'bipolar') |
---|
458 | if isempty(ActuatorDeviceList{iActFam}) |
---|
459 | if DisplayFlag |
---|
460 | fprintf(' %s family nominal value is %f [%s]\n', ActuatorFamily{iActFam}, InitActuator(1), ActuatorStart{iActFam}.UnitsString); |
---|
461 | fprintf(' Changing family by %+f [%s] from nominal\n', -ActuatorDelta{iActFam}(1)/2, ActuatorStart{iActFam}.UnitsString); |
---|
462 | drawnow; |
---|
463 | end |
---|
464 | DeltaActuator = InitActuator-ActuatorDelta{iActFam}/2; |
---|
465 | setsp(ActuatorFamily{iActFam}, DeltaActuator, ActuatorDeviceList{iActFam}, WaitFlag, InputFlags{:}); |
---|
466 | else |
---|
467 | if DisplayFlag |
---|
468 | fprintf(' %d. %s%s(%d,%d) nominal value is %f [%s]\n', iActDevice, CommonName, ActuatorFamily{iActFam}, ActuatorDeviceList{iActFam}(iActDevice,:), InitActuator(iActDevice), ActuatorStart{iActFam}.UnitsString); |
---|
469 | fprintf(' %d. Changing actuator by %+f [%s] from nominal\n', iActDevice, -ActuatorDelta{iActFam}(iActDevice)/2, ActuatorStart{iActFam}.UnitsString); |
---|
470 | drawnow; |
---|
471 | end |
---|
472 | DeltaActuator = InitActuator(iActDevice)-ActuatorDelta{iActFam}(iActDevice)/2; |
---|
473 | setsp(ActuatorFamily{iActFam}, DeltaActuator, ActuatorDeviceList{iActFam}(iActDevice,:), WaitFlag, InputFlags{:}); |
---|
474 | end |
---|
475 | elseif strcmpi(ModulationMethod, 'unipolar') |
---|
476 | if isempty(ActuatorDeviceList{iActFam}) |
---|
477 | DeltaActuator = InitActuator(1); |
---|
478 | else |
---|
479 | DeltaActuator = InitActuator(iActDevice); |
---|
480 | end |
---|
481 | if DisplayFlag |
---|
482 | if isempty(ActuatorDeviceList{iActFam}) |
---|
483 | fprintf(' %s family nominal value is %f [%s]\n', ActuatorFamily{iActFam}, InitActuator(1), ActuatorStart{iActFam}.UnitsString); |
---|
484 | %fprintf(' No change to actuator\n'); |
---|
485 | drawnow; |
---|
486 | else |
---|
487 | fprintf(' %d. %s%s(%d,%d) nominal value is %f [%s]\n', iActDevice, CommonName, ActuatorFamily{iActFam}, ActuatorDeviceList{iActFam}(iActDevice,:), InitActuator(iActDevice), ActuatorStart{iActFam}.UnitsString); |
---|
488 | %fprintf(' %d. No change to actuator\n', iActDevice); |
---|
489 | drawnow; |
---|
490 | end |
---|
491 | end |
---|
492 | end |
---|
493 | |
---|
494 | catch err |
---|
495 | fprintf(' %s\n', lasterr); |
---|
496 | if isempty(ActuatorDeviceList{iActFam}) |
---|
497 | FamilyMessage = sprintf('An error occurred setting %s to %f [%s].\n', ActuatorFamily{iActFam}, InitActuator(iActDevice), DeltaActuator, ActuatorStart{iActFam}.UnitsString); |
---|
498 | else |
---|
499 | FamilyMessage = sprintf('An error occurred setting %s(%d,%d) to %f [%s].\n', ActuatorFamily{iActFam}, ActuatorDeviceList{iActFam}(iActDevice,:), DeltaActuator, ActuatorStart{iActFam}.UnitsString); |
---|
500 | end |
---|
501 | CommandInput = questdlg( ... |
---|
502 | strvcat(FamilyMessage, ... |
---|
503 | strvcat('Either manually varify that the magnet is at the proper setpoint', ... |
---|
504 | strvcat('and continue measuring the response matrix or stop','the response matrix measurement?'))), ... |
---|
505 | 'MEASRESPMAT', ... |
---|
506 | 'Continue', ... |
---|
507 | 'Stop', ... |
---|
508 | 'Continue'); |
---|
509 | switch CommandInput |
---|
510 | case 'Stop' |
---|
511 | error('Response matrix measurement stopped.'); |
---|
512 | %S = {} |
---|
513 | %return; |
---|
514 | case 'Continue' |
---|
515 | %keyboard |
---|
516 | end |
---|
517 | end |
---|
518 | |
---|
519 | % Wait for signal processing if requested |
---|
520 | sleep(ExtraDelay); |
---|
521 | |
---|
522 | %if DisplayFlag |
---|
523 | % fprintf(' Recording data point #1\n'); drawnow; |
---|
524 | %end |
---|
525 | |
---|
526 | % Acquire data |
---|
527 | if WaitFlagMonitor == -5 |
---|
528 | Xm = getam(MonitorFamily, MonitorDeviceList, 'Manual', UnitsFlagCell{:}); |
---|
529 | else |
---|
530 | Xm = getam(MonitorFamily, MonitorDeviceList, InputFlags{:}); |
---|
531 | end |
---|
532 | |
---|
533 | % Step actuator up |
---|
534 | try |
---|
535 | if strcmpi(ModulationMethod, 'bipolar') |
---|
536 | if isempty(ActuatorDeviceList{iActFam}) |
---|
537 | if DisplayFlag |
---|
538 | fprintf(' Changing family by %+f [%s] from nominal\n', ActuatorDelta{iActFam}(1)/2, ActuatorStart{iActFam}.UnitsString); |
---|
539 | drawnow; |
---|
540 | end |
---|
541 | DeltaActuator = InitActuator+ActuatorDelta{iActFam}/2; |
---|
542 | setsp(ActuatorFamily{iActFam}, DeltaActuator, ActuatorDeviceList{iActFam}, WaitFlag, InputFlags{:}); |
---|
543 | else |
---|
544 | if DisplayFlag |
---|
545 | fprintf(' %d. Changing actuator by %+f [%s] from nominal\n', iActDevice, ActuatorDelta{iActFam}(iActDevice)/2, ActuatorStart{iActFam}.UnitsString); |
---|
546 | drawnow; |
---|
547 | end |
---|
548 | DeltaActuator = InitActuator(iActDevice)+ActuatorDelta{iActFam}(iActDevice)/2; |
---|
549 | setsp(ActuatorFamily{iActFam}, DeltaActuator, ActuatorDeviceList{iActFam}(iActDevice,:), WaitFlag, InputFlags{:}); |
---|
550 | end |
---|
551 | elseif strcmpi(ModulationMethod, 'unipolar') |
---|
552 | if isempty(ActuatorDeviceList{iActFam}) |
---|
553 | if DisplayFlag |
---|
554 | fprintf(' Changing family by %+f [%s] from nominal\n', ActuatorDelta{iActFam}(1), ActuatorStart{iActFam}.UnitsString); |
---|
555 | drawnow; |
---|
556 | end |
---|
557 | DeltaActuator = InitActuator+ActuatorDelta{iActFam}; |
---|
558 | setsp(ActuatorFamily{iActFam}, DeltaActuator, ActuatorDeviceList{iActFam}, WaitFlag, InputFlags{:}); |
---|
559 | else |
---|
560 | if DisplayFlag |
---|
561 | fprintf(' %d. Changing actuator by %+f [%s] from nominal\n', iActDevice, ActuatorDelta{iActFam}(iActDevice), ActuatorStart{iActFam}.UnitsString); |
---|
562 | drawnow; |
---|
563 | end |
---|
564 | DeltaActuator = InitActuator(iActDevice)+ActuatorDelta{iActFam}(iActDevice); |
---|
565 | setsp(ActuatorFamily{iActFam}, DeltaActuator, ActuatorDeviceList{iActFam}(iActDevice,:), WaitFlag, InputFlags{:}); |
---|
566 | end |
---|
567 | end |
---|
568 | catch err |
---|
569 | fprintf(' %s\n', lasterr); |
---|
570 | if isempty(ActuatorDeviceList{iActFam}) |
---|
571 | FamilyMessage = sprintf('An error occurred setting %s to %f [%s].\n', ActuatorFamily{iActFam}, InitActuator(iActDevice), DeltaActuator, ActuatorStart{iActFam}.UnitsString); |
---|
572 | else |
---|
573 | FamilyMessage = sprintf('An error occurred setting %s(%d,%d) to %f [%s].\n', ActuatorFamily{iActFam}, ActuatorDeviceList{iActFam}(iActDevice,:), DeltaActuator, ActuatorStart{iActFam}.UnitsString); |
---|
574 | end |
---|
575 | CommandInput = questdlg( ... |
---|
576 | strvcat(FamilyMessage, ... |
---|
577 | strvcat('Either manually varify that the magnet is at the proper setpoint', ... |
---|
578 | strvcat('and continue measuring the response matrix or stop','the response matrix measurement?'))), ... |
---|
579 | 'MEASRESPMAT', ... |
---|
580 | 'Continue', ... |
---|
581 | 'Stop', ... |
---|
582 | 'Continue'); |
---|
583 | switch CommandInput |
---|
584 | case 'Stop' |
---|
585 | error('Response matrix measurement stopped.'); |
---|
586 | %S = {} |
---|
587 | %return; |
---|
588 | case 'Continue' |
---|
589 | %keyboard |
---|
590 | end |
---|
591 | end |
---|
592 | |
---|
593 | % Wait for signal processing if requested |
---|
594 | sleep(ExtraDelay); |
---|
595 | |
---|
596 | if DisplayFlag |
---|
597 | %fprintf(' Recording data point #2\n'); drawnow; |
---|
598 | end |
---|
599 | |
---|
600 | % Acquire data |
---|
601 | if WaitFlagMonitor == -5 |
---|
602 | Xp = getam(MonitorFamily, MonitorDeviceList, 'Manual', UnitsFlagCell{:}); |
---|
603 | else |
---|
604 | Xp = getam(MonitorFamily, MonitorDeviceList, InputFlags{:}); |
---|
605 | end |
---|
606 | |
---|
607 | % Restore actuators |
---|
608 | try |
---|
609 | if isempty(ActuatorDeviceList{iActFam}) |
---|
610 | DeltaActuator = InitActuator; |
---|
611 | if WaitFlag == -2 |
---|
612 | WaitFlagReset = -1; |
---|
613 | else |
---|
614 | WaitFlagReset = WaitFlag; |
---|
615 | end |
---|
616 | setsp(ActuatorFamily{iActFam}, InitActuator, ActuatorDeviceList{iActFam}, WaitFlagReset, InputFlags{:}); |
---|
617 | if DisplayFlag |
---|
618 | if strcmpi(ActuatorStart{iActFam}.Mode, 'Manual') |
---|
619 | fprintf(' %s family reset\n', ActuatorFamily{iActFam}); |
---|
620 | else |
---|
621 | FinalSP = getsp(ActuatorFamily{iActFam}, InputFlags{:}); |
---|
622 | fprintf(' %s family reset to %f [%s]\n', ActuatorFamily{iActFam}, FinalSP(1), ActuatorStart{iActFam}.UnitsString); |
---|
623 | end |
---|
624 | end |
---|
625 | else |
---|
626 | DeltaActuator = InitActuator(iActDevice); |
---|
627 | if WaitFlag == -2 |
---|
628 | WaitFlagReset = -1; |
---|
629 | else |
---|
630 | WaitFlagReset = WaitFlag; |
---|
631 | end |
---|
632 | setsp(ActuatorFamily{iActFam}, InitActuator(iActDevice), ActuatorDeviceList{iActFam}(iActDevice,:), WaitFlagReset, InputFlags{:}); |
---|
633 | if DisplayFlag |
---|
634 | if strcmpi(ActuatorStart{iActFam}.Mode,'Manual') |
---|
635 | fprintf(' %d. %s%s(%d,%d) reset\n', iActDevice, CommonName, ActuatorFamily{iActFam}, ActuatorDeviceList{iActFam}(iActDevice,:)); |
---|
636 | else |
---|
637 | fprintf(' %d. %s%s(%d,%d) reset to %f [%s]\n', iActDevice, CommonName, ActuatorFamily{iActFam}, ActuatorDeviceList{iActFam}(iActDevice,:), getsp(ActuatorFamily{iActFam},ActuatorDeviceList{iActFam}(iActDevice,:)), ActuatorStart{iActFam}.UnitsString); |
---|
638 | end |
---|
639 | end |
---|
640 | end |
---|
641 | drawnow; |
---|
642 | catch |
---|
643 | fprintf(' %s\n', lasterr); |
---|
644 | if isempty(ActuatorDeviceList{iActFam}) |
---|
645 | FamilyMessage = sprintf('An error occurred setting %s to %f [%s].\n', ActuatorFamily{iActFam}, InitActuator(iActDevice), DeltaActuator, ActuatorStart{iActFam}.UnitsString); |
---|
646 | else |
---|
647 | FamilyMessage = sprintf('An error occurred setting %s(%d,%d) to %f [%s].\n', ActuatorFamily{iActFam}, ActuatorDeviceList{iActFam}(iActDevice,:), DeltaActuator, ActuatorStart{iActFam}.UnitsString); |
---|
648 | end |
---|
649 | CommandInput = questdlg( ... |
---|
650 | strvcat(FamilyMessage, ... |
---|
651 | strvcat('Either manually varify that the magnet is at the proper setpoint', ... |
---|
652 | strvcat('and continue measuring the response matrix or stop','the response matrix measurement?'))), ... |
---|
653 | 'MEASRESPMAT', ... |
---|
654 | 'Continue', ... |
---|
655 | 'Stop', ... |
---|
656 | 'Continue'); |
---|
657 | switch CommandInput |
---|
658 | case 'Stop' |
---|
659 | error('Response matrix measurement stopped.'); |
---|
660 | %S = {} |
---|
661 | %return; |
---|
662 | case 'Continue' |
---|
663 | %keyboard |
---|
664 | end |
---|
665 | end |
---|
666 | |
---|
667 | if DisplayFlag && (iActDevice < iActDeviceTotal{iActFam}) |
---|
668 | fprintf('\n'); |
---|
669 | end |
---|
670 | |
---|
671 | % Compute differences |
---|
672 | for iMonFam = 1:length(MonitorFamily) |
---|
673 | if isempty(ActuatorDeviceList{iActFam}) |
---|
674 | % Compute response matrix columns |
---|
675 | % For each magnet: 1. Divide by the change in amperes, like [Tune / Ampere] |
---|
676 | % 2. Scale each magnet by its fractional contribution in physics units (should use K*L, not just K) |
---|
677 | if strcmpi(family2units(ActuatorFamily{iActFam},'Setpoint'),'Hardware') |
---|
678 | DeltaPhysics = hw2physics(ActuatorFamily{iActFam}, 'Setpoint', InitActuator+ActuatorDelta{iActFam}, ActuatorDeviceList{iActFam}, ModeFlagCell{:}) - hw2physics(ActuatorFamily{iActFam}, 'Setpoint', InitActuator, ActuatorDeviceList{iActFam}, ModeFlagCell{:}); |
---|
679 | else |
---|
680 | DeltaPhysics = ActuatorDelta{iActFam}; |
---|
681 | end |
---|
682 | |
---|
683 | % DeltaPhysics should be K*Leff (not just "K") |
---|
684 | Leff = getleff(ActuatorFamily{iActFam}, ActuatorDeviceList{iActFam}); |
---|
685 | |
---|
686 | % Zero Leff is trouble, just divide by the number of actuators |
---|
687 | i = find(Leff==0); |
---|
688 | Leff(i) = 1 / length(Leff); |
---|
689 | |
---|
690 | DeltaPhysics = DeltaPhysics .* Leff; |
---|
691 | |
---|
692 | % In order to backout the response at each magnet, assume that |
---|
693 | % the response at each magnet is equal in physics units. |
---|
694 | DeltaMonitorPerPhysicsUnit = (Xp{iMonFam}-Xm{iMonFam}) / sum(DeltaPhysics); |
---|
695 | |
---|
696 | % Expand to each magnet |
---|
697 | R{iMonFam} = DeltaMonitorPerPhysicsUnit * ones(1,length(DeltaPhysics)); |
---|
698 | |
---|
699 | % When in hardware unit convert to delta monitor / ampere |
---|
700 | if strcmpi(family2units(ActuatorFamily{iActFam},'Setpoint'),'Hardware') |
---|
701 | PhysicsUnitPerAmp = DeltaPhysics ./ ActuatorDelta{iActFam}; |
---|
702 | for n = 1:length(DeltaPhysics) |
---|
703 | R{iMonFam}(:,n) = PhysicsUnitPerAmp(n) * R{iMonFam}(:,n); |
---|
704 | end |
---|
705 | end |
---|
706 | |
---|
707 | else |
---|
708 | % Just divide the monitor value by the actuator value |
---|
709 | R{iMonFam}(:,iActDevice) = (Xp{iMonFam}-Xm{iMonFam}) / ActuatorDelta{iActFam}(iActDevice); |
---|
710 | end |
---|
711 | |
---|
712 | % Save the measurements |
---|
713 | Monitor1{iMonFam}(:,iActDevice) = Xm{iMonFam}; |
---|
714 | Monitor2{iMonFam}(:,iActDevice) = Xp{iMonFam}; |
---|
715 | |
---|
716 | end % iMonFam |
---|
717 | |
---|
718 | % If the beam current is too low, prompt for a refill |
---|
719 | if DCCTStopFlag |
---|
720 | if (getdcct - DCCTStop) < 0 |
---|
721 | CommandInput = questdlg( ... |
---|
722 | {sprintf('The present beam current is %f', getdcct), ... |
---|
723 | sprintf('A refill prompt was requested at %f', DCCTStop), ... |
---|
724 | ' ', ... |
---|
725 | 'Your choices are:' |
---|
726 | sprintf('Continue - Continue and you will be prompted again a %f', DCCTStop), ... |
---|
727 | 'Stop - Stop the measure right now', ... |
---|
728 | 'Don''t ask again - Continue on without another interruption'}, ... |
---|
729 | 'MEASRESPMAT', ... |
---|
730 | 'Continue', ... |
---|
731 | 'Stop', ... |
---|
732 | 'Don''t ask again', 'Don''t ask again'); |
---|
733 | if isempty(CommandInput) || strcmp(CommandInput, 'Don''t ask again') |
---|
734 | DCCTStopFlag = 0; |
---|
735 | elseif strcmp(CommandInput, 'Stop') |
---|
736 | StopNow = 1; |
---|
737 | break; |
---|
738 | end |
---|
739 | end |
---|
740 | end |
---|
741 | |
---|
742 | end % iActDevice |
---|
743 | |
---|
744 | for iMonFam = 1:length(MonitorFamily) |
---|
745 | if StructOutputFlag |
---|
746 | S{iMonFam,iActFam}.Data = R{iMonFam}; |
---|
747 | |
---|
748 | S{iMonFam,iActFam}.Monitor = MonitorStart{iMonFam}; |
---|
749 | S{iMonFam,iActFam}.Actuator = ActuatorStart{iActFam}; |
---|
750 | S{iMonFam,iActFam}.ActuatorDelta = ActuatorDelta{iActFam}; |
---|
751 | |
---|
752 | S{iMonFam,iActFam}.Monitor1 = Monitor1{iMonFam}; |
---|
753 | S{iMonFam,iActFam}.Monitor2 = Monitor2{iMonFam}; |
---|
754 | |
---|
755 | if ~strcmpi(MonitorStart{iMonFam}.Units, ActuatorStart{iActFam}.Units) |
---|
756 | S{iMonFam,iActFam}.Units = [MonitorStart{iMonFam}.Units, '/', ActuatorStart{iActFam}.Units]; |
---|
757 | fprintf(' Warning: Units are in a mixed mode'); |
---|
758 | else |
---|
759 | S{iMonFam,iActFam}.Units = MonitorStart{iMonFam}.Units; |
---|
760 | end |
---|
761 | %S{iMonFam,iActFam}.UnitsString = ['[',MonitorStart{iMonFam}.UnitsString,']', '/', '[',ActuatorStart{iActFam}.UnitsString,']']; |
---|
762 | S{iMonFam,iActFam}.UnitsString = [MonitorStart{iMonFam}.UnitsString, '/', ActuatorStart{iActFam}.UnitsString]; |
---|
763 | |
---|
764 | S{iMonFam,iActFam}.GeV = getenergy(ModeFlagCell{:}); |
---|
765 | S{iMonFam,iActFam}.TimeStamp = t0; |
---|
766 | S{iMonFam,iActFam}.DCCT = DCCTStart; |
---|
767 | S{iMonFam,iActFam}.ModulationMethod = ModulationMethod; |
---|
768 | S{iMonFam,iActFam}.WaitFlag = WaitFlagMonitor; |
---|
769 | S{iMonFam,iActFam}.ExtraDelay = ExtraDelay; |
---|
770 | S{iMonFam,iActFam}.DataDescriptor = 'Response Matrix'; |
---|
771 | S{iMonFam,iActFam}.CreatedBy = 'measrespmat'; |
---|
772 | S{iMonFam,iActFam}.OperationalMode = getfamilydata('OperationalMode'); |
---|
773 | else |
---|
774 | S{iMonFam,iActFam} = R{iMonFam}; |
---|
775 | end |
---|
776 | end |
---|
777 | |
---|
778 | if StopNow |
---|
779 | break; |
---|
780 | end |
---|
781 | |
---|
782 | end |
---|
783 | |
---|
784 | |
---|
785 | % For one family inputs, there is no need for a cell output |
---|
786 | if all(size(S) == [1 1]) |
---|
787 | S = S{1}; |
---|
788 | end |
---|
789 | |
---|