1 | function ffgettbl(Sector, BPMFlag, QUADGenFlag) |
---|
2 | %FFGETBL - Gets a new insertion device feedforward table |
---|
3 | % ffgettbl(Sector, BPMFlag(1=BPM, 2=IDBPM), QUADGenFlag (0-take the old quad table, else){0}) |
---|
4 | % |
---|
5 | % This function generates the feed forward tables necessary for insertion device compensation. |
---|
6 | % |
---|
7 | % See also fftest, ffanal |
---|
8 | |
---|
9 | % |
---|
10 | % Written by ALS people |
---|
11 | |
---|
12 | % TODO |
---|
13 | % Needs adaptation for SOLEIL |
---|
14 | |
---|
15 | alsglobe |
---|
16 | |
---|
17 | % Initialize |
---|
18 | if nargin < 3 |
---|
19 | QUADGenFlag = 0; % 0 -> Do not compute a quadrupole table |
---|
20 | end |
---|
21 | |
---|
22 | % Check bpm sample rate |
---|
23 | checkbpmavg(2); |
---|
24 | checkidbpmavg(2); |
---|
25 | sca_sleep(.5); |
---|
26 | |
---|
27 | % Initialization |
---|
28 | BPMTol = .005; |
---|
29 | BPMIter = 5; |
---|
30 | IDBPMTol = .0003; |
---|
31 | IDBPMIter = 5; |
---|
32 | |
---|
33 | Navg = 1; |
---|
34 | IDVel = 3.33; |
---|
35 | FFDate = date; |
---|
36 | FFClock = clock; |
---|
37 | FFGeV = GeV; |
---|
38 | |
---|
39 | gap=[]; |
---|
40 | hcm=[]; |
---|
41 | vcm=[]; |
---|
42 | |
---|
43 | |
---|
44 | % Check/Get inputs |
---|
45 | if isempty(GLOBAL_SR_GEV) |
---|
46 | disp(' Storage ring energy is unknown. Run alsinit then run ffgettbl.'); disp(' '); |
---|
47 | return; |
---|
48 | end |
---|
49 | |
---|
50 | |
---|
51 | disp([' ']); disp(' '); |
---|
52 | disp([' INSERTION DEVICE FEED FORWARD TABLE GENERATION APPLICATION']); |
---|
53 | disp([' ']); |
---|
54 | disp([' This program will generate a feed forward table at ',num2str(GeV), ' GeV. If this is']); |
---|
55 | disp(' not the correct beam energy, exit (enter 0 for Sector) and run alsinit.'); |
---|
56 | disp(' Before continuing, make sure the following conditions are true. '); |
---|
57 | disp(' 1. Multi-bunch mode.'); |
---|
58 | disp(' 2. FF disabled.'); |
---|
59 | disp(' 3. Gap Control disabled.'); |
---|
60 | disp(' 4. Current range: typically 35-45 mAmps, but any current should be OK.'); |
---|
61 | disp(' 5. Production corrector magnet set.'); |
---|
62 | disp(' 6. Bumps off and BTS 3 and 4 set to zero current.'); |
---|
63 | disp(' 7. BPMs calibrated.'); |
---|
64 | disp(' 8. Set the insertion device Velocity Profiling off (0) (just for speed).'); |
---|
65 | disp(' 9. Slow orbit feedback off.'); |
---|
66 | |
---|
67 | if QUADGenFlag |
---|
68 | disp(' 10. Tune measure system must be on (time between updates < 5 seconds).'); |
---|
69 | end |
---|
70 | |
---|
71 | if nargin < 1 |
---|
72 | %Sector = input(' Sector (0-exit, 4, 5, 7, 8, 9, 12) = '); |
---|
73 | SectorIn = menu(str2mat(sprintf('%.1f GeV Feed Forward Generation',GeV),'Feed forward must be off!',' ','Which insertion device?'),'4-vertical','4-longitudinal','5','7','8','9','10','12','Cancel'); |
---|
74 | if SectorIn == 1 |
---|
75 | % Sector 4 vertical using new feedforward method |
---|
76 | Sector = 4; |
---|
77 | ffgettblepugap; |
---|
78 | return |
---|
79 | elseif SectorIn == 2 |
---|
80 | % Sector 4 longitudinal using new feedforward method |
---|
81 | Sector = 4; |
---|
82 | ffgettblepushift; |
---|
83 | %ffgettblepu; % old method |
---|
84 | return |
---|
85 | elseif SectorIn == 3 |
---|
86 | Sector = 5; |
---|
87 | elseif SectorIn == 4 |
---|
88 | Sector = 7; |
---|
89 | elseif SectorIn == 5 |
---|
90 | Sector = 8; |
---|
91 | elseif SectorIn == 6 |
---|
92 | Sector = 9; |
---|
93 | elseif SectorIn == 7 |
---|
94 | Sector = 10; |
---|
95 | elseif SectorIn == 8 |
---|
96 | Sector = 12; |
---|
97 | elseif SectorIn == 9 |
---|
98 | disp(' ffgettbl aborted. No changes to correctors or insertion device.'); |
---|
99 | return |
---|
100 | end |
---|
101 | end |
---|
102 | disp(' '); |
---|
103 | |
---|
104 | if Sector == 0 |
---|
105 | disp(' ffgettbl aborted. No changes to correctors or insertion device.'); |
---|
106 | return; |
---|
107 | end |
---|
108 | |
---|
109 | if Sector == 5 |
---|
110 | QUADFlag = 1; % 1 -> use quadrupoles |
---|
111 | else |
---|
112 | QUADFlag = 0; % 0 -> no not use quadrupoles |
---|
113 | end |
---|
114 | |
---|
115 | if size(Sector) == [1 1] |
---|
116 | % input ok |
---|
117 | else |
---|
118 | disp(' ffgettbl aborted. Input must to a scalar.'); |
---|
119 | return; |
---|
120 | end |
---|
121 | |
---|
122 | |
---|
123 | % Minimum and maximum gap |
---|
124 | [GAPmin, GAPmax] = gaplimit(Sector); |
---|
125 | |
---|
126 | |
---|
127 | disp([' The insertion device for sector ',num2str(Sector),' has been selected.']); |
---|
128 | disp([' Maximum Gap = ',num2str(GAPmax),' mm']); |
---|
129 | disp([' Mimimum Gap = ',num2str(GAPmin),' mm']); |
---|
130 | |
---|
131 | if nargin < 2 |
---|
132 | BPMFlag = 2; %menu1('Which BPM family to use for table generation?','96 arc sector BPMs only.','Straight section IDBPMs only.','Exit program.'); |
---|
133 | end |
---|
134 | if isempty(BPMFlag) |
---|
135 | BPMFlag = 2; |
---|
136 | end |
---|
137 | |
---|
138 | if BPMFlag > 2 |
---|
139 | disp(' ffgettbl aborted, BPMFlag > 2. No changes to correctors or insertion device.'); |
---|
140 | return; |
---|
141 | end |
---|
142 | |
---|
143 | disp([' Data collection started. Figures 1 and 2 show the difference orbits between the maximum']); |
---|
144 | disp([' gap and the current gap position after the feed forward correction has been applied. ']); |
---|
145 | disp([' Ideally, these plots should be a straight line thru zero, however, due to orbit drift, BPM']); |
---|
146 | disp([' noise, and feed forward imperfections one can expect 10 or 20 microns of combined errors']); |
---|
147 | disp([' to accumulate before minimum gap is reached (hopefully not any more than that).']); |
---|
148 | disp([' ']); |
---|
149 | |
---|
150 | |
---|
151 | % Change to physics data directory |
---|
152 | DirStart = pwd; |
---|
153 | gotodata |
---|
154 | cd gaptrack |
---|
155 | |
---|
156 | |
---|
157 | if QUADGenFlag==0 & QUADFlag |
---|
158 | disp(' Reading the old feed forward table for quadrupole compensation.'); |
---|
159 | [tableXold, tableYold, tableQold] = fftable(Sector, GeV); |
---|
160 | end |
---|
161 | |
---|
162 | |
---|
163 | % Create output file names |
---|
164 | tmp = clock; |
---|
165 | year = tmp(1); |
---|
166 | month = tmp(2); |
---|
167 | day = tmp(3); |
---|
168 | hour = tmp(4); |
---|
169 | minute = tmp(5); |
---|
170 | seconds= tmp(6); |
---|
171 | matfn1 = sprintf('id%02de%.0f', Sector, 10*GeV); |
---|
172 | matfn2 = sprintf('id%02de%.0f_%4d-%02d-%02d', Sector, 10*GeV, year, month, day); |
---|
173 | textfn1 = sprintf('id%02de%.0f.txt', Sector, 10*GeV); |
---|
174 | textfn2 = sprintf('id%02de%.0f_%4d-%02d-%02d.txt', Sector, 10*GeV, year, month, day); |
---|
175 | |
---|
176 | |
---|
177 | % Setup figures |
---|
178 | Buffer = .01; |
---|
179 | HeightBuffer = .05; |
---|
180 | |
---|
181 | h1=figure; |
---|
182 | set(h1,'units','normal','position',[.0+Buffer .5+Buffer .5-2*Buffer .5-2*Buffer-HeightBuffer]); |
---|
183 | |
---|
184 | h2=figure(h1+1); |
---|
185 | set(h2,'units','normal','position',[.5+Buffer .5+Buffer .5-2*Buffer .5-2*Buffer-HeightBuffer]); |
---|
186 | |
---|
187 | |
---|
188 | % Corrector magnet and BPM lists |
---|
189 | HCMlist1 = [Sector-1 8; |
---|
190 | Sector 1]; |
---|
191 | |
---|
192 | VCMlist1 = [Sector-1 8; |
---|
193 | Sector 1]; |
---|
194 | |
---|
195 | HCMlistQuad = [Sector-1 2; |
---|
196 | Sector 7]; |
---|
197 | |
---|
198 | VCMlistQuad = [Sector-1 2; |
---|
199 | Sector 7]; |
---|
200 | |
---|
201 | IDBPMlist1 = IDBPMlist; % Remove the IDBPMs in the sector where the ID is located. |
---|
202 | RemoveElem = find(Sector==IDBPMlist(:,1)); |
---|
203 | IDBPMlist1(RemoveElem,:) = []; |
---|
204 | |
---|
205 | |
---|
206 | % Set gap to maximum, set velocity to maximum, velocity profile off, FF off |
---|
207 | setff([], 0, 0); |
---|
208 | setid(Sector, GAPmax, IDVel, 1, 0); |
---|
209 | scasleep(1); |
---|
210 | |
---|
211 | |
---|
212 | % Setbumps |
---|
213 | setbumps(Sector, 1); % No sextupole correctors |
---|
214 | scasleep(1); |
---|
215 | |
---|
216 | |
---|
217 | % Starting orbit and corrector magnet |
---|
218 | [x210a, y210a] = getbpm(1, Navg); |
---|
219 | [IDx210a, IDy210a] = getidbpm(1, Navg); |
---|
220 | HCM0 = getsp('HCM', HCMlist1); |
---|
221 | VCM0 = getsp('VCM', VCMlist1); |
---|
222 | HCMQuad0 = getsp('HCM', HCMlistQuad); |
---|
223 | VCMQuad0 = getsp('VCM', VCMlistQuad); |
---|
224 | QF0 = getsp('QF', [Sector-1 1;Sector 2]); |
---|
225 | QD0 = getsp('QD', [Sector-1 1;Sector 2]); |
---|
226 | |
---|
227 | |
---|
228 | % Main loop |
---|
229 | i=1; |
---|
230 | gap(i,1) = getid(Sector); |
---|
231 | hcm(i,:) = (getsp('HCM', HCMlist1)-HCM0)'; |
---|
232 | vcm(i,:) = (getsp('VCM', VCMlist1)-VCM0)'; |
---|
233 | |
---|
234 | if QUADFlag |
---|
235 | hcmquad = []; |
---|
236 | vcmquad = []; |
---|
237 | qf = []; |
---|
238 | qd = []; |
---|
239 | |
---|
240 | hcmquad(i,:) = (getsp('HCM', HCMlistQuad)-HCMQuad0)'; |
---|
241 | vcmquad(i,:) = (getsp('VCM', VCMlistQuad)-VCMQuad0)'; |
---|
242 | |
---|
243 | qf(i,:) = (getsp('QF', [Sector-1 1;Sector 2])-QF0)'; |
---|
244 | qd(i,:) = (getsp('QD', [Sector-1 1;Sector 2])-QD0)'; |
---|
245 | |
---|
246 | if QUADGenFlag |
---|
247 | scasleep(5); |
---|
248 | tune(i,:) = gettune'; |
---|
249 | end |
---|
250 | end |
---|
251 | |
---|
252 | [X(:,i), Y(:,i)] = getbpm(1, Navg); |
---|
253 | [IDX(:,i), IDY(:,i)] = getidbpm(1, Navg); |
---|
254 | Xrms(i) = std(x210a-X(:,i)); |
---|
255 | Yrms(i) = std(y210a-Y(:,i)); |
---|
256 | XrmsGoal(i) = std(x210a-X(:,i)); |
---|
257 | YrmsGoal(i) = std(y210a-Y(:,i)); |
---|
258 | IterOut(i) = 1; |
---|
259 | |
---|
260 | if GAPmin < 17 |
---|
261 | Gaps = [(GAPmax-10):-10:60 56:-4:36 34.5:-1.5:19.5 19:-.5:GAPmin]; |
---|
262 | elseif GAPmin < 34 |
---|
263 | Gaps = [(GAPmax-10):-10:60 56:-4:36 34.5:-1.5:GAPmin]; |
---|
264 | elseif GAPmin < 55 |
---|
265 | Gaps = [(GAPmax-10):-10:60 56:-4:GAPmin]; |
---|
266 | else |
---|
267 | Gaps = [(GAPmax-10):-10:GAPmin]; |
---|
268 | end |
---|
269 | |
---|
270 | |
---|
271 | for i = 2:length(Gaps)+1 |
---|
272 | g = Gaps(i-1); |
---|
273 | |
---|
274 | % Set gap |
---|
275 | setid(Sector, g, IDVel); |
---|
276 | |
---|
277 | % Set to old table first |
---|
278 | %setsp('HCM', HCM0+tableXold(i,2:3)', HCMlist1); % this does not seem to be a good idea |
---|
279 | %setsp('VCM', VCM0+tableYold(i,2:3)', VCMlist1); % need to linear fit the data if you do use this??? |
---|
280 | |
---|
281 | scasleep(1); |
---|
282 | |
---|
283 | % Correct orbit |
---|
284 | if BPMFlag == 1 |
---|
285 | % BPM least squares |
---|
286 | [STDfinal, IterOut(i)] = setbpm('HCM', x210a, HCMlist1, BPMelem, ... |
---|
287 | 'VCM', y210a, VCMlist1, BPMelem, BPMIter, BPMTol); |
---|
288 | IDXrmsGoal(i) = STDfinal(1); |
---|
289 | IDYrmsGoal(i) = STDfinal(2); |
---|
290 | else |
---|
291 | % IDBPM least squares |
---|
292 | IDxGoal = IDx210a; |
---|
293 | IDxGoal(RemoveElem) = []; |
---|
294 | |
---|
295 | IDyGoal = IDy210a; |
---|
296 | IDyGoal(RemoveElem) = []; |
---|
297 | |
---|
298 | [STDfinal, IterOut(i)] = setidbpm('HCM', IDxGoal, HCMlist1, IDBPMlist1, ... |
---|
299 | 'VCM', IDyGoal, VCMlist1, IDBPMlist1, IDBPMIter, IDBPMTol); |
---|
300 | IDXrmsGoal(i) = STDfinal(1); |
---|
301 | IDYrmsGoal(i) = STDfinal(2); |
---|
302 | end |
---|
303 | |
---|
304 | |
---|
305 | % Record the gap AM |
---|
306 | gap(i,1) = getid(Sector); |
---|
307 | |
---|
308 | |
---|
309 | % Correct tune |
---|
310 | if QUADFlag |
---|
311 | IDxGoal = getidx; |
---|
312 | IDyGoal = getidy; |
---|
313 | |
---|
314 | if QUADGenFlag |
---|
315 | % Generate a new quadrupole table |
---|
316 | scasleep(5); |
---|
317 | settunew(Sector, tune(1,:)', 1); |
---|
318 | scasleep(1); |
---|
319 | |
---|
320 | % Correct orbit using IDBPM least squares |
---|
321 | [STDfinal, IterOut] = setidbpm('HCM', IDxGoal, HCMlistQuad, IDBPMlist, ... |
---|
322 | 'VCM', IDyGoal, VCMlistQuad, IDBPMlist, IDBPMIter, IDBPMTol); |
---|
323 | |
---|
324 | scasleep(5); |
---|
325 | tune(i,:) = gettune'; |
---|
326 | fprintf(' Gap=%.3f mm, TuneX=%.5f, TuneY=%.5f\n', gap(i), 14+tune(i,1), 8+tune(i,2)); |
---|
327 | pause(0); |
---|
328 | |
---|
329 | else |
---|
330 | % Base quadrupole setting on the old table |
---|
331 | tmpgap = gap(i); |
---|
332 | |
---|
333 | % just to make table1 work |
---|
334 | if tmpgap >= tableQold(1,1) |
---|
335 | tmpgap = tableQold(1,1); |
---|
336 | end |
---|
337 | if tmpgap <= tableQold(size(tableQold,1),1) |
---|
338 | tmpgap = tableQold(size(tableQold,1),1); |
---|
339 | end |
---|
340 | DelQF1 = table1([tableQold(:,1) tableQold(:,2)], tmpgap); |
---|
341 | DelQF2 = table1([tableQold(:,1) tableQold(:,3)], tmpgap); |
---|
342 | DelQD1 = table1([tableQold(:,1) tableQold(:,4)], tmpgap); |
---|
343 | DelQD2 = table1([tableQold(:,1) tableQold(:,5)], tmpgap); |
---|
344 | |
---|
345 | setsp('QF', QF0 + [DelQF1; DelQF2], [Sector-1 1; Sector 2]); |
---|
346 | setsp('QD', QD0 + [DelQD1; DelQD2], [Sector-1 1; Sector 2]); |
---|
347 | |
---|
348 | if all([DelQF1 DelQF2 DelQD1 DelQD2] == [0 0 0 0]) |
---|
349 | % Don't correct the orbit |
---|
350 | else |
---|
351 | scasleep(1); |
---|
352 | % Correct orbit using IDBPM least squares |
---|
353 | [STDfinal, IterOut] = setidbpm('HCM', IDxGoal, HCMlistQuad, IDBPMlist, ... |
---|
354 | 'VCM', IDyGoal, VCMlistQuad, IDBPMlist, IDBPMIter, IDBPMTol); |
---|
355 | end |
---|
356 | |
---|
357 | % Since the tune measurement system is probably not on, fill with zeros |
---|
358 | tune(i,:) = [0 0]; %gettune'; |
---|
359 | end |
---|
360 | |
---|
361 | qf(i,:) = (getsp('QF', [Sector-1 1;Sector 2])-QF0)'; |
---|
362 | qd(i,:) = (getsp('QD', [Sector-1 1;Sector 2])-QD0)'; |
---|
363 | |
---|
364 | hcmquad(i,:) = (getsp('HCM', HCMlistQuad)-HCMQuad0)'; |
---|
365 | vcmquad(i,:) = (getsp('VCM', VCMlistQuad)-VCMQuad0)'; |
---|
366 | end |
---|
367 | |
---|
368 | |
---|
369 | % Record data |
---|
370 | hcm(i,:) = (getsp('HCM', HCMlist1)-HCM0)'; |
---|
371 | vcm(i,:) = (getsp('VCM', VCMlist1)-VCM0)'; |
---|
372 | [X(:,i), Y(:,i)] = getbpm(1, Navg); |
---|
373 | [IDX(:,i), IDY(:,i)] = getidbpm(1, Navg); |
---|
374 | |
---|
375 | |
---|
376 | % Statistics |
---|
377 | Xrms(i) = std(x210a-X(:,i)); |
---|
378 | Yrms(i) = std(y210a-Y(:,i)); |
---|
379 | IDXrms(i) = std(IDx210a-IDX(:,i)); |
---|
380 | IDYrms(i) = std(IDy210a-IDY(:,i)); |
---|
381 | |
---|
382 | |
---|
383 | % plot results |
---|
384 | figure(h1); % BPMs |
---|
385 | plot(BPMs,(X(:,i)-x210a)*1000,'r', BPMs,(Y(:,i)-y210a)*1000,'g'); |
---|
386 | title(['BPM Orbit Error at a ', num2str(gap(i,1)),' mm Gap']); |
---|
387 | ylabel('X (red), Y (grn) Error [microns]'); |
---|
388 | xlabel('BPM Position [meters]'); |
---|
389 | |
---|
390 | figure(h2); % IDBPMs |
---|
391 | plot(IDBPMs(IDBPMelem),(IDX(:,i)-IDx210a)*1000,'r', IDBPMs(IDBPMelem),(IDY(:,i)-IDy210a)*1000,'g'); |
---|
392 | title(['IDBPM Orbit Error at a ', num2str(gap(i,1)),' mm Gap']); |
---|
393 | ylabel('X (red), Y (grn) Error [microns]'); |
---|
394 | xlabel('IDBPM Position [meters]'); |
---|
395 | |
---|
396 | drawnow |
---|
397 | end |
---|
398 | |
---|
399 | |
---|
400 | % Minimum gap orbits |
---|
401 | [xmin, ymin] = getbpm(1, Navg); |
---|
402 | [IDxmin, IDymin] = getidbpm(1, Navg); |
---|
403 | |
---|
404 | |
---|
405 | % Make the FF-tables |
---|
406 | if QUADFlag |
---|
407 | % Tables |
---|
408 | tableX = [gap hcm(:,1)-hcm(1,1) hcm(:,2)-hcm(1,2) hcmquad]; |
---|
409 | tableY = [gap vcm(:,1)-vcm(1,1) vcm(:,2)-vcm(1,2) vcmquad]; |
---|
410 | tableQ = [gap qf qd tune]; |
---|
411 | else |
---|
412 | % Tables |
---|
413 | tableX = [gap hcm(:,1)-hcm(1,1) hcm(:,2)-hcm(1,2)]; |
---|
414 | tableY = [gap vcm(:,1)-vcm(1,1) vcm(:,2)-vcm(1,2)]; |
---|
415 | tableQ = []; |
---|
416 | end |
---|
417 | |
---|
418 | |
---|
419 | % Reset gap and correctors |
---|
420 | disp(' The insertion device gap and the correctors are being reset.'); |
---|
421 | disp(' '); |
---|
422 | |
---|
423 | |
---|
424 | if QUADFlag |
---|
425 | % Reset the quadrupole in steps (or the beam will dump) |
---|
426 | i = length(gap)-2; |
---|
427 | setid(Sector, gap(i), IDVel); |
---|
428 | setsp('QF', QF0+qf(i,:)', [Sector-1 1;Sector 2]); |
---|
429 | setsp('QD', QD0+qd(i,:)', [Sector-1 1;Sector 2]); |
---|
430 | setsp('HCM', HCMQuad0+hcmquad(i,:)', HCMlistQuad); |
---|
431 | setsp('VCM', VCMQuad0+vcmquad(i,:)', VCMlistQuad); |
---|
432 | |
---|
433 | i = length(gap)-6; |
---|
434 | setid(Sector, gap(i), IDVel); |
---|
435 | setsp('QF', QF0+qf(i,:)', [Sector-1 1;Sector 2]); |
---|
436 | setsp('QD', QD0+qd(i,:)', [Sector-1 1;Sector 2]); |
---|
437 | setsp('HCM', HCMQuad0+hcmquad(i,:)', HCMlistQuad); |
---|
438 | setsp('VCM', VCMQuad0+vcmquad(i,:)', VCMlistQuad); |
---|
439 | |
---|
440 | i = length(gap)-10; |
---|
441 | setid(Sector, gap(i), IDVel); |
---|
442 | setsp('QF', QF0+qf(i,:)', [Sector-1 1;Sector 2]); |
---|
443 | setsp('QD', QD0+qd(i,:)', [Sector-1 1;Sector 2]); |
---|
444 | setsp('HCM', HCMQuad0+hcmquad(i,:)', HCMlistQuad); |
---|
445 | setsp('VCM', VCMQuad0+vcmquad(i,:)', VCMlistQuad); |
---|
446 | |
---|
447 | % Reset to max gap values |
---|
448 | setsp('QF', QF0, [Sector-1 1;Sector 2]); |
---|
449 | setsp('QD', QD0, [Sector-1 1;Sector 2]); |
---|
450 | setsp('HCM', HCMQuad0, HCMlistQuad); |
---|
451 | setsp('VCM', VCMQuad0, VCMlistQuad); |
---|
452 | end |
---|
453 | |
---|
454 | |
---|
455 | % Go to max gap |
---|
456 | setid(Sector, GAPmax, IDVel); |
---|
457 | setsp('HCM', HCM0, HCMlist1); |
---|
458 | setsp('VCM', VCM0, VCMlist1); |
---|
459 | |
---|
460 | |
---|
461 | % Ending orbits |
---|
462 | scasleep(2); |
---|
463 | [x210b, y210b] = getbpm(1, Navg); |
---|
464 | [IDx210b, IDy210b] = getidbpm(1, Navg); |
---|
465 | |
---|
466 | |
---|
467 | % Save in matlab/srdata/gaptrack |
---|
468 | % Save in Matlab format (binary format) |
---|
469 | CreatedGeV = GLOBAL_SR_GEV; |
---|
470 | CreatedDateStr = date; |
---|
471 | CreatedClock = clock; |
---|
472 | CreatedByStr = 'ffgettbl'; |
---|
473 | ReadmeStr = sprintf('%.1f GeV feed forward table saved to %s.mat in directory %s', GLOBAL_SR_GEV, matfn1, pwd); |
---|
474 | idbpmlist = IDBPMlist; |
---|
475 | eval(['save ', matfn1,' CreatedGeV CreatedDateStr CreatedClock CreatedByStr ReadmeStr BPMFlag X Y IDX IDY x210a y210a x210b y210b IDx210a IDy210a IDx210b IDy210b xmin ymin IDxmin IDymin idbpmlist tableX tableY tableQ Xrms Yrms IDXrms IDYrms IDXrmsGoal IDYrmsGoal IterOut FFDate FFClock FFGeV']); |
---|
476 | |
---|
477 | |
---|
478 | % Save in text format |
---|
479 | fid = fopen(textfn1,'wt'); |
---|
480 | if BPMFlag == 1 |
---|
481 | fprintf(fid,'#SR%02d %.1f GeV %02.0f-%02.0f-%.0f %02.0f:%02.0f:%02.0f BPM\n', Sector, GeV, month, day, year, hour, minute, seconds); |
---|
482 | else |
---|
483 | fprintf(fid,'#SR%02d %.1f GeV %02.0f-%02.0f-%.0f %02.0f:%02.0f:%02.0f IDBPM\n', Sector, GeV, month, day, year, hour, minute, seconds); |
---|
484 | end |
---|
485 | |
---|
486 | if QUADFlag |
---|
487 | fprintf(fid,'#Gap HCM(S-1,8) HCM(S,1) VCM(S-1,8) VCM(S,1) HCM(S-1,2) HCM(S,7) VCM(S-1,2) VCM(S,7) QF(S-1,1) QF(S,2) QD(S-1,1) QD(S,2)\n'); |
---|
488 | for i=1:size(tableX,1) |
---|
489 | fprintf(fid,'%.4f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f\n', tableX(i,1), tableX(i,2), tableX(i,3), tableY(i,2), tableY(i,3), hcmquad(i,1), hcmquad(i,2), vcmquad(i,1), vcmquad(i,2), qf(i,1), qf(i,2), qd(i,1), qd(i,2)); |
---|
490 | end |
---|
491 | fclose(fid); |
---|
492 | else |
---|
493 | % Normal FF |
---|
494 | fprintf(fid,'#Gap HCM4 HCM1 VCM4 VCM1\n'); |
---|
495 | for i=1:size(tableX,1) |
---|
496 | fprintf(fid,'%.4f %.3f %.3f %.3f %.3f\n', tableX(i,1), tableX(i,2), tableX(i,3), tableY(i,2), tableY(i,3)); |
---|
497 | end |
---|
498 | fclose(fid); |
---|
499 | end |
---|
500 | fprintf(' Data saved to %s\n', [pwd, '/', textfn1]); |
---|
501 | |
---|
502 | |
---|
503 | % Save in w:\public\matlab\gaptrack\archive with the date in the file name |
---|
504 | % Save in Matlab format (binary format) |
---|
505 | cd archive |
---|
506 | eval(['save ', matfn2,' CreatedGeV CreatedDateStr CreatedClock CreatedByStr ReadmeStr BPMFlag X Y IDX IDY x210a y210a x210b y210b IDx210a IDy210a IDx210b IDy210b xmin ymin IDxmin IDymin idbpmlist tableX tableY tableQ Xrms Yrms IDXrms IDYrms IDXrmsGoal IDYrmsGoal IterOut FFDate FFClock FFGeV']); |
---|
507 | |
---|
508 | % Save in text format |
---|
509 | fid = fopen(textfn2,'wt'); |
---|
510 | if BPMFlag == 1 |
---|
511 | fprintf(fid,'#SR%02d %.1f GeV %02.0f-%02.0f-%.0f %02.0f:%02.0f:%02.0f BPM\n', Sector, GeV, month, day, year, hour, minute, seconds); |
---|
512 | else |
---|
513 | fprintf(fid,'#SR%02d %.1f GeV %02.0f-%02.0f-%.0f %02.0f:%02.0f:%02.0f IDBPM\n', Sector, GeV, month, day, year, hour, minute, seconds); |
---|
514 | end |
---|
515 | |
---|
516 | if QUADFlag |
---|
517 | fprintf(fid,'#Gap HCM(S-1,8) HCM(S,1) VCM(S-1,8) VCM(S,1) HCM(S-1,2) HCM(S,7) VCM(S-1,2) VCM(S,7) QF(S-1,1) QF(S,2) QD(S-1,1) QD(S,2)\n'); |
---|
518 | for i=1:size(tableX,1) |
---|
519 | fprintf(fid,'%.4f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f\n', tableX(i,1), tableX(i,2), tableX(i,3), tableY(i,2), tableY(i,3), hcmquad(i,1), hcmquad(i,2), vcmquad(i,1), vcmquad(i,2), qf(i,1), qf(i,2), qd(i,1), qd(i,2)); |
---|
520 | end |
---|
521 | fclose(fid); |
---|
522 | else |
---|
523 | % Normal FF |
---|
524 | fprintf(fid,'#Gap HCM4 HCM1 VCM4 VCM1\n'); |
---|
525 | for i=1:size(tableX,1) |
---|
526 | fprintf(fid,'%.4f %.3f %.3f %.3f %.3f\n', tableX(i,1), tableX(i,2), tableX(i,3), tableY(i,2), tableY(i,3)); |
---|
527 | end |
---|
528 | fclose(fid); |
---|
529 | end |
---|
530 | fprintf(' Data saved to %s\n', [pwd, '/', textfn2]); |
---|
531 | cd .. |
---|
532 | |
---|
533 | % Close figures then ffanal |
---|
534 | close(h1); |
---|
535 | close(h2); |
---|
536 | FigureHandles = ffanal(Sector, GeV); |
---|
537 | |
---|
538 | |
---|
539 | disp([' Measurement complete. The gap position and correctors have been set back to their original setpoints.']); |
---|
540 | disp([' A new table has been generated and saved to directory /home/als/physdata/matlab/srdata/gaptrack.']); |
---|
541 | disp([' If the table has been successfully generated, the RMS error over the full range of gap positions will be']); |
---|
542 | disp([' below 10 microns (see Fig. 2), however it is probably OK to except a table with up to 25 microns of error.']); |
---|
543 | disp([' Figure ', num2str(FigureHandles(1)),' -> Corrector strength verses gap position.']); |
---|
544 | disp([' Figure ', num2str(FigureHandles(2)),' -> RMS orbit distortion verses gap position.']); |
---|
545 | disp([' Figure ', num2str(FigureHandles(3)),' -> Orbit drift during table generation verses BPM position.']); |
---|
546 | disp([' Figure ', num2str(FigureHandles(4)),' -> Rate of Change of the Corrector Magnets.']); |
---|
547 | |
---|
548 | |
---|
549 | CPTableFlag = questdlg(sprintf('Copy %.1f GeV Table to the IOC?',GeV),'Feed Forward Table Complete','Yes','No','No'); |
---|
550 | if strcmp(CPTableFlag,'No') |
---|
551 | fprintf(' Use ffcopy(%d,%.1f) to copy the table over to the feed forward program.\n', Sector, GeV); |
---|
552 | fprintf(' Use ffread(%d) (or the "Undulator Server" application) to force the IOC to read the new table.\n', Sector); |
---|
553 | else |
---|
554 | ffcopy(textfn1); |
---|
555 | fprintf(' For the IOC to read the new table use the "Undulator Server"\n'); |
---|
556 | fprintf(' application or run ffread(%d) from Matlab.\n', Sector); |
---|
557 | end |
---|
558 | |
---|
559 | |
---|
560 | % Return of original directory |
---|
561 | eval(['cd ', DirStart]); |
---|
562 | |
---|
563 | |
---|
564 | % Close figures |
---|
565 | %for i = 1:length(FigureHandles) |
---|
566 | % close(FigureHandles(i)); |
---|
567 | %end |
---|
568 | |
---|
569 | |
---|
570 | fprintf(' ffgettbl function complete.\n'); |
---|
571 | |
---|