source: MML/trunk/machine/SOLEIL/StorageRing/bba_mml/quadcenter.m @ 4

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

Initial import--MML version from SOLEIL@2013

File size: 36.8 KB
Line 
1function [QMS1, QMS2] = quadcenter(QuadFamily, QuadDev, XYPlane, FigureHandle)
2%QUADCENTER - Measure the magnet center of a quadrupole magnet
3%  [QMS1, QMS2] = quadcenter(QuadFamily, QuadDev, XYPlane, FigureHandle)
4%                     or
5%  [QMS1, QMS2] = quadcenter(QMSstructure, FigureHandle)
6%
7%  Finds the center of an individual quadrupole magnet.
8%  The data is automatically appended to quadcenter.log and
9%  saved to an individual mat file named by family, sector, and element number
10%
11%  INPUTS
12%  1. QuadFamily  = Family name
13%  2. QuadDev     = Device list for quadrupole family
14%  3. XYPlane     = 0 -> both horizontal and vertical {default}
15%                   1 -> horizontal only
16%                   2 -> vertical only
17%  4. FigureHandle can be a figure handle, a vector of 4 axes handles
18%                 (used by quadplot), or zero for no plots
19%
20%  The QuadFamily and QuadDev input get converted to a QMSstructure using quadcenterinit. 
21%  One can also directly input this data structure.
22%  QMSstructure =
23%         QuadFamily: Quadrupole family name, like 'QF'
24%            QuadDev: Quadrupole device, like [7 1]
25%          QuadDelta: Modulation amplitude in the quadrupole, like 1
26%          QuadPlane: Horizontal (1) or vertical (2) plane
27%         CorrFamily: Corrector magnet family, like 'HCM'
28%        CorrDevList: Corrector magnet(s) using to vary the orbit in the quadrupole, like [7 1]
29%          CorrDelta: Maximum change in the corrector(s), like 0.5000
30%          BPMFamily: BPM family name, like 'BPMx'
31%             BPMDev: BPM device next to the quadrupole, like [7 1]
32%         BPMDevList: BPM device list used calculate the center and for orbit correction ([nx2 array])
33%   ModulationMethod: Method for changing the quadrupole
34%                         'bipolar' changes the quadrupole by +/- QuadDelta on each step
35%                         'unipolar' changes the quadrupole from 0 to QuadDelta on each step
36%                         'sweep' moves the quadrupole by QuadDelta at each step.  This allows for
37%                                 staying on a given hysteresis branch.
38%     NumberOfPoints: Number of points, like 3
39%      DataDirectory: Directory to store the results.  Leave this field out or '.' will put the data
40%                         in the present directory.
41%       QuadraticFit: 0 = linear fit, else quadratic fit  (used by quadplot)
42%      OutlierFactor: if abs(data - fit) > OutlierFactor, then remove that BPM from the center calculation [mm] (used by quadplot)
43%         ExtraDelay: Extra delay added before reading the BPMs [seconds] {optional}
44%
45%  OUTPUTS
46%  The QMSstructure input structure will get the following output fields appended to it. 
47%  This structure will be output as well as saved to a file which is named based on the
48%  sector, quadrupole family name, and device number.  A log file will also be updated.
49%  QMSstructure =
50%          OldCenter: Old quadrupole center (from getoffsetorbit)
51%                 x1: horizonal data at quadrupole value #1
52%                 x2: horizonal data at quadrupole value #2
53%                 y1: vertical data at quadrupole value #1
54%                 y2: vertical data at quadrupole value #2
55%               Xerr: Horizonal BPM starting error
56%               Yerr: Vertical  BPM starting error
57%          TimeStamp: Time stamp as output by clock (6 element vector)
58%          CreatedBy: 'quadcenter'
59%      QMS.BPMStatus: Status of the BPMs
60%         QMS.BPMSTD: Standard deviation of the BPMs (from getsigma)
61%             Center: Mean of the BPM center calculations
62%          CenterSTD: Standard deviation of the BPM center calculations
63%  For two planes, QMS1 is the horizontal and QMS2 is the vertical.  When only finding
64%  one plane, only the first output is used.  For multiple magnets, the output is a column
65%  vector containing the quadrupole center.
66%
67%  NOTE
68%  1. It is a good idea to have the global orbit reasonable well corrected at the start
69%  2. If the quadrupole modulation system is not a simple device with one family name then
70%     edit the setquad function (machine specific).
71%  3. For the new BPM offsets to take effect, they must be loaded into the main AO data structure.
72%  4. This program changes the MML warning level to -2 -> Dialog Box
73%     That way the measurement can be salvaged if something goes wrong
74%
75%  Machine specific setup:
76%  1. setquad and getquad must exist for setting and getting the quadrupole current.
77%     These function are often machine dependent.
78
79%
80%  Written by Greg Portmann
81%
82%  Laurent S. Nadolski, November 2009
83%  Modified Figure handler 1008 in H-plane 1010 in V-plane
84
85
86% Extra delay can be written over by the QMS.ExtraDelay field.  If this
87% does not exist, then the value below is used.
88ExtraDelay = 0;
89
90
91% Set the waitflag on power supply setpoints to wait for fresh data from the BPMs
92WaitFlag = -2;
93
94
95% Record the tune at each point.
96% In simulate mode the tunes are always saved unless the TUNE family does not exist.
97GetTuneFlag = 1;
98
99
100% Inputs
101QMS1 = [];
102QMS2 = [];
103if nargin < 1
104    FamilyList = getfamilylist;
105    [tmp,i] = ismemberof(FamilyList,'QUAD');
106    if ~isempty(i)
107        FamilyList = FamilyList(i,:);
108    end
109    if size(FamilyList,1) == 1
110        QuadFamily = deblank(FamilyList);
111    else
112        [i,ok] = listdlg('PromptString', 'Select a quadrupole family:', ...
113            'SelectionMode', 'single', ...
114            'ListString', FamilyList);
115        if ok == 0
116            return
117        else
118            QuadFamily = deblank(FamilyList(i,:));
119        end
120    end
121end
122
123if isstruct(QuadFamily)
124    QMS = QuadFamily;
125    XYPlane = QMS.QuadPlane;
126    if QMS.QuadPlane == 1
127        QMS_Horizontal = QMS;
128        QMS_Vertical   = quadcenterinit(QMS.QuadFamily, QMS.QuadDev, 2);
129        QMS_Vertical.CorrectOrbit = QMS.CorrectOrbit;
130    elseif QMS.QuadPlane == 2
131        QMS_Horizontal = quadcenterinit(QMS.QuadFamily, QMS.QuadDev, 1);
132        QMS_Horizontal.CorrectOrbit = QMS.CorrectOrbit;
133        QMS_Vertical = QMS;
134    else
135        error('QMS.QuadPlane must be 1 or 2 when using a QMS structure input');
136    end
137    if nargin >= 2
138        FigureHandle = QuadDev;
139    else
140        FigureHandle = [];
141    end
142    QuadFamily = QMS.QuadFamily;
143    QuadDev    = QMS.QuadDev;
144else
145    if ~isfamily(QuadFamily)
146        error(sprintf('Quadrupole family %s does not exist.  Make sure the middle layer had been initialized properly.',QuadFamily));
147    end
148    if nargin < 2
149        QuadDev = editlist(getlist(QuadFamily),QuadFamily,zeros(length(getlist(QuadFamily)),1));
150    end
151    if nargin < 3
152        ButtonNumber = menu('Which Plane?', 'Both','Horizontal Only','Vertical Only','Cancel'); 
153        drawnow;
154        switch ButtonNumber
155            case 1
156                XYPlane = 0;
157            case 2
158                XYPlane = 1;
159            case 3
160                XYPlane = 2;
161            otherwise
162                fprintf('   quadcenter cancelled\n');
163                return
164        end
165    end
166    if nargin < 4
167        FigureHandle = [];
168    end
169   
170    % If QuadDev is a vector
171    if size(QuadDev,1) > 1
172        for i = 1:size(QuadDev,1)
173            if XYPlane == 0
174                [Q1, Q2] = quadcenter(QuadFamily, QuadDev(i,:), XYPlane, FigureHandle);
175                QMS1(i,1) = Q1.Center;
176                QMS2(i,1) = Q2.Center;
177            else
178                [Q1] = quadcenter(QuadFamily, QuadDev(i,:), XYPlane, FigureHandle);
179                QMS1(i,1) = Q1.Center;
180            end
181        end
182        return
183    end
184   
185   
186    % Get QMS structure
187    QMS_Horizontal = quadcenterinit(QuadFamily, QuadDev, 1);
188    QMS_Vertical   = quadcenterinit(QuadFamily, QuadDev, 2);
189end
190
191
192% Change the MML warning level to -2 -> Dialog Box
193% That way the measurement can be salvaged if something goes wrong
194ErrorWarningLevel = getfamilydata('ErrorWarningLevel');
195setfamilydata(-2, 'ErrorWarningLevel');
196
197
198% Initialize variables
199HCMFamily  = QMS_Horizontal.CorrFamily;
200HCMDev     = QMS_Horizontal.CorrDevList;
201DelHCM     = QMS_Horizontal.CorrDelta;
202BPMxFamily = QMS_Horizontal.BPMFamily;
203BPMxDev    = QMS_Horizontal.BPMDev;
204BPMxDevList= QMS_Horizontal.BPMDevList;
205
206VCMFamily  = QMS_Vertical.CorrFamily;
207VCMDev     = QMS_Vertical.CorrDevList;
208DelVCM     = QMS_Vertical.CorrDelta;
209BPMyFamily = QMS_Vertical.BPMFamily;
210BPMyDev    = QMS_Vertical.BPMDev;
211BPMyDevList= QMS_Vertical.BPMDevList;
212
213Xcenter = NaN;
214Ycenter = NaN;
215
216
217% Check status for BPMs next to the quadrupole and correctors used in orbit correction
218HCMStatus = family2status(HCMFamily, HCMDev);
219
220if ~isnan(HCMStatus) && any(HCMStatus==0)
221    error(sprintf('A %s corrector used in finding the center has a bad status', HCMFamily));
222end
223VCMStatus = family2status(VCMFamily, VCMDev);
224if ~isnan(VCMStatus) && any(VCMStatus==0)
225    error(sprintf('A %s corrector used in finding the center has a bad status', VCMFamily));
226end
227BPMxStatus = family2status(BPMxFamily, BPMxDev);
228if ~isnan(BPMxStatus) && any(BPMxStatus==0)
229    error(sprintf('The %s monitor next to the quadrupole has bad status', BPMxFamily));
230end
231BPMyStatus = family2status(BPMxFamily, BPMxDev);
232if ~isnan(BPMyStatus) && any(BPMyStatus==0)
233    error(sprintf('The %s monitor next to the quadrupole has bad status', BPMxFamily));
234end
235
236   
237% Record start directory
238DirStart = pwd;
239
240% Get the current offset orbit
241Xoffset = getoffset(BPMxFamily, BPMxDev);
242Yoffset = getoffset(BPMyFamily, BPMyDev);
243XoffsetOld = Xoffset;
244YoffsetOld = Yoffset;
245
246% Starting correctors
247HCM00 = getsp(HCMFamily, HCMDev);
248VCM00 = getsp(VCMFamily, VCMDev);
249
250
251% % Global orbit correction
252% CM = getsp('HCM','struct');
253% BPM = getx('struct');
254% BPMWeight = ones(size(BPM.DeviceList,1),1);
255% i = findrowindex(BPMxDev, BPM.DeviceList);
256%
257% x = getoffset('BPMx');
258% x = .1 * BPMWeight;
259% %x(i) = -.2;
260% BPMWeight(i) = 100;
261%
262% setorbit(x, BPM, CM, 3, 20, BPMWeight, 'Display');
263
264
265% Correct orbit to the old offsets first
266if strcmpi(QMS_Horizontal.CorrectOrbit, 'yes')
267    fprintf('   Correcting the orbit to the old horizontal center of %s(%d,%d)\n', QuadFamily, QuadDev); pause(0);
268    if ~isnan(Xoffset)
269        OrbitCorrection(Xoffset, BPMxFamily, BPMxDev, HCMFamily, HCMDev, 4);
270    end
271end
272if strcmpi(QMS_Vertical.CorrectOrbit, 'yes')
273    fprintf('   Correcting the orbit to the old vertical center of %s(%d,%d)\n', QuadFamily, QuadDev); pause(0);
274    if ~isnan(Yoffset)
275        OrbitCorrection(Yoffset, BPMyFamily, BPMyDev, VCMFamily, VCMDev, 4);
276    end
277end
278
279%OrbitCorrection(Xoffset, BPMxFamily, BPMxDev, HCMFamily, HCMDev);
280%OrbitCorrection(Yoffset, BPMyFamily, BPMyDev, VCMFamily, VCMDev);
281
282
283
284% Algorithm
285% 1.  Change the horizontal orbit in the quad
286% 2.  Correct the vertical orbit
287% 3.  Record the orbit
288% 4.  Step the quad
289% 5.  Record the orbit
290
291% Start by sollicitating the BPMs in TANGO
292% in order to avoid timeout
293getx; getz;
294
295% FIND HORIZONTAL OFFSET
296if XYPlane==0 || XYPlane==1   
297    FigureHandle = 1008;
298       
299    % BPM processor delay
300    if isfield(QMS_Horizontal, 'ExtraDelay')
301        ExtraDelay = QMS_Horizontal.ExtraDelay;
302    end
303
304    % Get mode
305    Mode = getmode(QMS_Horizontal.QuadFamily);
306   
307    % Record starting point
308    QUAD0 = getquad(QMS_Horizontal);
309    HCM0  = getsp(HCMFamily, HCMDev);
310    VCM0  = getsp(VCMFamily, VCMDev);
311    Xerr  = getam(BPMxFamily, BPMxDev) - Xoffset;
312    Yerr  = getam(BPMyFamily, BPMyDev) - Yoffset;
313    xstart = getam(BPMxFamily, BPMxDevList);
314    ystart = getam(BPMyFamily, BPMyDevList);
315
316    QMS_Horizontal.Orbit0 = getam(BPMxFamily, BPMxDevList, 'Struct');
317   
318    [tmp, iNotFound] = findrowindex(BPMxDev, BPMxDevList);
319    if ~isempty(iNotFound)
320        setsp(HCMFamily, HCM00, HCMDev, 0);
321        setsp(VCMFamily, VCM00, VCMDev, 0);
322        error('BPM at the quadrupole not found in the BPM device list');
323    end
324     
325    DelQuad = QMS_Horizontal.QuadDelta;
326    N = abs(round(QMS_Horizontal.NumberOfPoints));
327    if N < 1
328        error('The number of points must be 2 or more.');
329    end
330   
331   
332    fprintf('   Finding horizontal center of %s(%d,%d)\n', QuadFamily, QuadDev);
333    fprintf('   Starting orbit error: %s(%d,%d)=%f , %s(%d,%d)=%f %s\n', BPMxFamily, BPMxDev, Xerr, BPMyFamily, BPMyDev, Yerr, QMS_Horizontal.Orbit0.UnitsString);
334    if strcmpi(QMS_Horizontal.ModulationMethod, 'bipolar')
335        fprintf('   Quadrupole starting current = %.3f, modulate by +/- %.3f\n', getquad(QMS_Horizontal), DelQuad);
336    elseif strcmpi(QMS_Horizontal.ModulationMethod, 'unipolar')
337        fprintf('   Quadrupole starting current = %.3f, modulate by 0 to %.3f\n', getquad(QMS_Horizontal), DelQuad);
338    elseif strcmpi(QMS_Horizontal.ModulationMethod, 'sweep')
339        fprintf('   Quadrupole starting current = %.3f, sweep by %.3f on each step\n', getquad(QMS_Horizontal), DelQuad);       
340    else
341        % Reset or error
342        setsp(HCMFamily, HCM00, HCMDev, 0);
343        setsp(VCMFamily, VCM00, VCMDev, 0);
344        setquad(QMS_Horizontal, QUAD0, 0);
345        cd(DirStart);
346        error('Unknown ModulationMethod in the QMS input structure (likely a problem with quadcenterinit)');
347    end
348    pause(0);
349   
350    % Establish a hysteresis loop
351    % Modified to always comes from the same side of hysteresis curve
352    if strcmpi(QMS_Horizontal.ModulationMethod, 'bipolar')
353        fprintf('   Establishing a hysteresis loop on the quadrupole (bi-polar case)\n'); pause(0);
354        setquad(QMS_Horizontal,-DelQuad+QUAD0, -1);
355        setquad(QMS_Horizontal,+DelQuad+QUAD0, -1);
356        setquad(QMS_Horizontal,-DelQuad+QUAD0, -1);
357        setquad(QMS_Horizontal,+DelQuad+QUAD0, -1);
358        setquad(QMS_Horizontal,         QUAD0, -1);
359    elseif strcmpi(QMS_Horizontal.ModulationMethod, 'unipolar')
360        fprintf('   Establishing a hysteresis loop on the quadrupole (uni-polar case)\n'); pause(0);
361        setquad(QMS_Horizontal, DelQuad+QUAD0, -1);
362        setquad(QMS_Horizontal,         QUAD0, -1);
363        setquad(QMS_Horizontal, DelQuad+QUAD0, -1);
364        setquad(QMS_Horizontal,         QUAD0, -1);
365    end
366   
367   
368    % Corrector step size
369    CorrStep = 2 * DelHCM / (N-1);
370
371   
372    % Start the corrector a little lower first for hysteresis reasons
373    %stepsp(HCMFamily, -1.0*DelHCM, HCMDev, -1);
374    stepsp(HCMFamily, -1.2*DelHCM, HCMDev, -1);
375    stepsp(HCMFamily,   .2*DelHCM, HCMDev, WaitFlag);
376
377   
378    % Main horizontal data loop
379    clear DCCT
380    for i = 1:N % Loop of corrector steps
381        % Step the horizontal orbit
382        if i ~= 1
383            stepsp(HCMFamily, CorrStep, HCMDev, WaitFlag);
384        end
385       
386        fprintf('   %d. %s(%d,%d) sp/am = %+.4f/%+.4f, %s(%d,%d) = %+.5f %s\n', i, HCMFamily, HCMDev(1,:), getsp(HCMFamily, HCMDev(1,:)), getam(HCMFamily, HCMDev(1,:)),  BPMxFamily, BPMxDev, getam(BPMxFamily, BPMxDev), QMS_Horizontal.Orbit0.UnitsString); pause(0); 
387       
388        % If correcting the orbit, then recorrect the vertical center now
389        if strcmpi(QMS_Horizontal.CorrectOrbit, 'yes')
390           % Correct the vertical orbit
391           OrbitCorrection(Yoffset, BPMyFamily, BPMyDev, VCMFamily, VCMDev, 4);
392        end
393       
394        if strcmpi(QMS_Horizontal.ModulationMethod, 'sweep')
395            % One directional sweep of the quadrupole
396            sleep(ExtraDelay);
397            x1(:,i) = getam(BPMxFamily, BPMxDevList);
398            y1(:,i) = getam(BPMyFamily, BPMyDevList);
399            x0(:,i) = x1(:,i);
400            y0(:,i) = y1(:,i);
401           
402            if (GetTuneFlag || strcmpi(Mode, 'Simulator')) && isfamily('TUNE')
403                QMS_Horizontal.Tune1(:,i) = gettune;
404            end
405
406            setquad(QMS_Horizontal, i*DelQuad+QUAD0, WaitFlag);
407            sleep(ExtraDelay);
408
409            % If correcting the orbit, then recorrect the horizontal center now
410            if strcmpi(QMS_Horizontal.CorrectOrbit, 'yes')
411                % Correct the vertical orbit
412                OrbitCorrection(Yoffset, BPMyFamily, BPMyDev, VCMFamily, VCMDev, 4);
413                sleep(ExtraDelay);
414            end
415
416            x2(:,i) = getam(BPMxFamily, BPMxDevList);
417            y2(:,i) = getam(BPMyFamily, BPMyDevList);
418           
419            if (GetTuneFlag || strcmpi(Mode, 'Simulator')) && isfamily('TUNE')
420                QMS_Horizontal.Tune2(:,i) = gettune;
421            end
422   
423        elseif strcmpi(QMS_Horizontal.ModulationMethod, 'bipolar')
424            % Modulate the quadrupole
425            sleep(ExtraDelay);
426            x0(:,i) = getam(BPMxFamily, BPMxDevList);
427            y0(:,i) = getam(BPMyFamily, BPMyDevList);
428            setquad(QMS_Horizontal, -DelQuad+QUAD0, WaitFlag);
429            sleep(ExtraDelay);
430
431            % If correcting the orbit, then recorrect the horizontal center now
432            if strcmpi(QMS_Horizontal.CorrectOrbit, 'yes')
433                % Correct the vertical orbit
434                OrbitCorrection(Yoffset, BPMyFamily, BPMyDev, VCMFamily, VCMDev, 4);
435                sleep(ExtraDelay);
436            end
437
438            x1(:,i) = getam(BPMxFamily, BPMxDevList);
439            y1(:,i) = getam(BPMyFamily, BPMyDevList);
440           
441            if (GetTuneFlag || strcmpi(Mode, 'Simulator')) && isfamily('TUNE')
442                QMS_Horizontal.Tune1(:,i) = gettune;
443            end
444
445            setquad(QMS_Horizontal,+DelQuad+QUAD0, WaitFlag);
446            sleep(ExtraDelay);
447
448            % If correcting the orbit, then recorrect the horizontal center now
449            if strcmpi(QMS_Horizontal.CorrectOrbit, 'yes')
450                % Correct the vertical orbit
451                OrbitCorrection(Yoffset, BPMyFamily, BPMyDev, VCMFamily, VCMDev, 4);
452                sleep(ExtraDelay);
453            end
454
455            x2(:,i) = getam(BPMxFamily, BPMxDevList);
456            y2(:,i) = getam(BPMyFamily, BPMyDevList);
457           
458            if (GetTuneFlag || strcmpi(Mode, 'Simulator')) && isfamily('TUNE')
459                QMS_Horizontal.Tune2(:,i) = gettune;
460            end
461
462            setquad(QMS_Horizontal, QUAD0, WaitFlag);
463       
464        elseif strcmpi(QMS_Horizontal.ModulationMethod, 'unipolar')
465            % Modulate the quadrupole
466            sleep(ExtraDelay);
467            x1(:,i) = getam(BPMxFamily, BPMxDevList);
468            y1(:,i) = getam(BPMyFamily, BPMyDevList);
469            x0(:,i) = x1(:,i);
470            y0(:,i) = y1(:,i);
471           
472            if (GetTuneFlag || strcmpi(Mode, 'Simulator')) && isfamily('TUNE')
473                QMS_Horizontal.Tune1(:,i) = gettune;
474            end
475
476            setquad(QMS_Horizontal, DelQuad+QUAD0, WaitFlag);
477            sleep(ExtraDelay);
478
479            % If correcting the orbit, then recorrect the horizontal center now
480            if strcmpi(QMS_Horizontal.CorrectOrbit, 'yes')
481                % Correct the vertical orbit
482                OrbitCorrection(Yoffset, BPMyFamily, BPMyDev, VCMFamily, VCMDev, 4);
483                sleep(ExtraDelay);
484            end
485
486            x2(:,i) = getam(BPMxFamily, BPMxDevList);
487            y2(:,i) = getam(BPMyFamily, BPMyDevList);
488           
489            if (GetTuneFlag || strcmpi(Mode, 'Simulator')) && isfamily('TUNE')
490                QMS_Horizontal.Tune2(:,i) = gettune;
491            end
492
493            setquad(QMS_Horizontal, QUAD0, WaitFlag);
494        end
495
496        DCCT(i) = getdcct;
497    end
498
499    % Get the horizontal data filename and save the data
500    % Append data and time
501    FileName = ['bba', num2str(QuadDev(1,1)), QuadFamily, num2str(QuadDev(1,2)), 'hplane'];
502    FileName = appendtimestamp(FileName, clock);
503
504    % Use a version number
505    %i=1;
506    %FileName = ['s', num2str(QuadDev(1,1)), QuadFamily, num2str(QuadDev(1,2)), 'h', num2str(i)];
507    %while exist([FileName,'.mat'], 'file')
508    %    i = i + 1;
509    %    FileName = ['s', num2str(QuadDev(1,1)), QuadFamily, num2str(QuadDev(1,2)), 'h', num2str(i)];
510    %end
511   
512    QMS = QMS_Horizontal;
513    QMS.QuadPlane = 1;
514   
515    QMS.OldCenter = Xoffset;
516    QMS.XOffsetOld = XoffsetOld;
517    QMS.YOffsetOld = YoffsetOld;
518   
519    QMS.xstart = xstart;
520    QMS.ystart = ystart;
521   
522    QMS.x0 = x0;
523    QMS.x1 = x1;
524    QMS.x2 = x2;
525    QMS.y0 = y0;
526    QMS.y1 = y1;
527    QMS.y2 = y2;
528    QMS.Xerr = Xerr;
529    QMS.Yerr = Yerr;
530    QMS.TimeStamp = clock;
531    QMS.DCCT = DCCT;
532    QMS.DataDescriptor = 'Quadrupole Center';
533    QMS.CreatedBy = 'quadcenter';
534   
535    % Get and store the BPM status and standard deviation (to be used by the center calculation routine)
536    QMS.BPMStatus = family2status(BPMxFamily, BPMxDevList);
537    N = getbpmaverages(BPMxDevList);
538    QMS.BPMSTD = getsigma(BPMxFamily, BPMxDevList, N);
539
540    % Set up figures, plot and find horizontal center
541    try
542        if isempty(FigureHandle)
543            QMS = quadplot(QMS);
544        else
545            QMS = quadplot(QMS, FigureHandle);
546        end
547        drawnow;
548    catch
549        fprintf('\n%s\n', lasterr);
550    end
551    QMS1 = QMS;
552
553    % Save the horizontal data
554    if isfield(QMS_Horizontal, 'DataDirectory')
555        [FinalDir, ErrorFlag] = gotodirectory(QMS_Horizontal.DataDirectory);
556    end
557    QMS.DataDirectory = pwd;
558    save(FileName, 'QMS');
559    fprintf('   Data saved to file %s in directory %s\n\n', FileName, QMS.DataDirectory);
560
561    % Output data to file
562    fid1 = fopen('quadcenter.log','at');
563    time=clock;
564    fprintf(fid1, '%s   %d:%d:%2.0f \n', date, time(4),time(5),time(6));
565    fprintf(fid1, 'Data saved to file %s (%s)\n', FileName, QMS.DataDirectory);
566    fprintf(fid1, '%s(%d,%d) %s(%d,%d) = %f (+/- %f) [%s]\n\n', QuadFamily, QuadDev, BPMxFamily, BPMxDev, QMS.Center, QMS.CenterSTD, QMS_Horizontal.Orbit0.UnitsString);
567    fclose(fid1);
568    cd(DirStart);
569
570    % Change the offset orbit to the new center so that the vertical plane uses it
571    Xoffset = QMS.Center;
572   
573    % Restore magnets their starting points (correctors to values after orbit correction)
574    setsp(HCMFamily, HCM0, HCMDev, WaitFlag);
575    setsp(VCMFamily, VCM0, VCMDev, WaitFlag);
576    setquad(QMS_Horizontal, QUAD0, WaitFlag);
577   
578    if (GetTuneFlag || strcmpi(Mode, 'Simulator')) && isfamily('TUNE')
579        % Print the tune information
580        fprintf('   Tune and tune difference for the 1st points in the merit function (QMS.Tune1): \n');
581        fprintf('   %8.5f', QMS.Tune1(1,:));
582        fprintf('  Horizontal\n');
583        fprintf('   %8.5f', QMS.Tune1(2,:));
584        fprintf('  Vertical\n');
585        fprintf('   ===================================================\n');
586        fprintf('   %8.5f', diff(QMS.Tune1));
587        fprintf('  Difference \n\n');
588       
589        fprintf('   Tune and tune difference for the 2nd points in the merit function (QMS.Tune2): \n');
590        fprintf('   %8.5f', QMS.Tune2(1,:));
591        fprintf('  Horizontal\n');
592        fprintf('   %8.5f', QMS.Tune2(2,:));
593        fprintf('  Vertical\n');
594        fprintf('   ===================================================\n');
595        fprintf('   %8.5f', diff(QMS.Tune2));
596        fprintf('  Difference\n\n');
597
598        dTune1 = diff(QMS.Tune1);
599        dTune2 = diff(QMS.Tune2);
600       
601        if any(sign(dTune1/dTune1(1))==-1)
602            fprintf('   Tune change sign!!!\n');           
603        end
604       
605        if any(abs(dTune1) < .025) || any(abs(dTune2) < .025)
606            fprintf('   Horizontal and vertical tunes seem too close.\n');
607        end
608    end   
609end
610
611
612
613% FIND VERTICAL OFFSET
614if XYPlane==0 || XYPlane==2   
615    FigureHandle = 1010;
616
617    % BPM processor delay
618    if isfield(QMS_Vertical, 'ExtraDelay')
619        ExtraDelay = QMS_Vertical.ExtraDelay;
620    end
621
622    % Get mode
623    Mode = getmode(QMS_Horizontal.QuadFamily);
624   
625    % Record starting point
626    QUAD0 = getquad(QMS_Vertical);
627    HCM0 = getsp(HCMFamily, HCMDev);
628    VCM0 = getsp(VCMFamily, VCMDev);
629    Xerr = getam(BPMxFamily, BPMxDev) - Xoffset;
630    Yerr = getam(BPMyFamily, BPMyDev) - Yoffset;
631    xstart = getam(BPMxFamily, BPMxDevList);
632    ystart = getam(BPMyFamily, BPMyDevList);
633   
634    QMS_Vertical.Orbit0 = getam(BPMxFamily, BPMxDevList, 'Struct');
635
636    [tmp, iNotFound] = findrowindex(BPMyDev, BPMyDevList);
637    if ~isempty(iNotFound)
638        setsp(HCMFamily, HCM00, HCMDev, 0);
639        setsp(VCMFamily, VCM00, VCMDev, 0);
640        error('BPM at the quadrupole not found in the BPM device list');
641    end
642
643    DelQuad = QMS_Vertical.QuadDelta;
644    N = abs(round(QMS_Vertical.NumberOfPoints));
645    if N < 1
646        error('The number of points must be 2 or more.');
647    end
648
649    fprintf('   Finding vertical center of %s(%d,%d)\n', QuadFamily, QuadDev);
650    fprintf('   Starting orbit error: %s(%d,%d)=%f , %s(%d,%d)=%f %s\n', BPMxFamily, BPMxDev, Xerr, BPMyFamily, BPMyDev, Yerr, QMS_Vertical.Orbit0.UnitsString);
651    if strcmpi(QMS_Vertical.ModulationMethod, 'bipolar')
652        fprintf('   Quadrupole starting current = %.3f, modulate by +/- %.3f\n', getquad(QMS_Vertical), DelQuad);
653    elseif strcmpi(QMS_Vertical.ModulationMethod, 'unipolar')
654        fprintf('   Quadrupole starting current = %.3f, modulate by 0 to %.3f\n', getquad(QMS_Vertical), DelQuad);
655    elseif strcmpi(QMS_Vertical.ModulationMethod, 'sweep')
656        fprintf('   Quadrupole starting current = %.3f, sweep by %.3f on each step\n', getquad(QMS_Vertical), DelQuad);
657    else
658        setsp(HCMFamily, HCM00, HCMDev, 0);
659        setsp(VCMFamily, VCM00, VCMDev, 0);
660        setquad(QMS_Vertical, QUAD0, 0);
661        cd(DirStart);
662        error('Unknown ModulationMethod in the QMS input structure (likely a problem with quadcenterinit)');
663    end
664    pause(0);
665   
666   
667    % Establish a hysteresis loop (if not already done, or if the horizontal plane was sweep)
668    if XYPlane == 2 || strcmpi(QMS_Horizontal.ModulationMethod, 'sweep')
669        if strcmpi(QMS_Vertical.ModulationMethod, 'bipolar')
670            fprintf('   Establishing a hysteresis loop on the quadrupole (bi-polar case)\n'); pause(0);
671            setquad(QMS_Vertical,-DelQuad*sign(QUAD0)+QUAD0, -1);
672            setquad(QMS_Vertical,+DelQuad*sign(QUAD0)+QUAD0, -1);
673            setquad(QMS_Vertical,-DelQuad*sign(QUAD0)+QUAD0, -1);
674            setquad(QMS_Vertical,+DelQuad*sign(QUAD0)+QUAD0, -1);
675            setquad(QMS_Vertical,         QUAD0, -1);
676        elseif strcmpi(QMS_Vertical.ModulationMethod, 'unipolar')
677            fprintf('   Establishing a hysteresis loop on the quadrupole (uni-polar case)\n'); pause(0);
678            setquad(QMS_Vertical, DelQuad*sign(QUAD0)+QUAD0, -1);
679            setquad(QMS_Vertical,         QUAD0, -1);
680            setquad(QMS_Vertical, DelQuad*sign(QUAD0)+QUAD0, -1);
681            setquad(QMS_Vertical,         QUAD0, -1);
682        end
683    end
684   
685
686    % Corrector step size
687    CorrStep = 2 * DelVCM / (N-1);
688
689   
690    % Start the corrector a little lower first for hysteresis reasons
691    stepsp(VCMFamily, -1.2*DelVCM, VCMDev, -1);
692    stepsp(VCMFamily,   .2*DelVCM, VCMDev, WaitFlag);
693
694
695%     Debug
696%     setquad(QMS_Vertical, DelQuad+QUAD0, WaitFlag);
697%     QUAD0 = getquad(QMS_Vertical);
698%     Xstart = getam(BPMxFamily, BPMxDev)
699   
700
701    clear DCCT
702    for i = 1:N
703
704        % Step the vertical orbit
705        if i ~= 1
706            stepsp(VCMFamily, CorrStep, VCMDev, WaitFlag);
707        end
708
709        fprintf('   %d. %s(%d,%d) sp/am = %+.4f/%+.4f, %s(%d,%d) = %+.5f %s\n', i, VCMFamily, VCMDev(1,:), getsp(VCMFamily, VCMDev(1,:)), getam(VCMFamily, VCMDev(1,:)),  BPMyFamily, BPMyDev, getam(BPMyFamily, BPMyDev), QMS_Vertical.Orbit0.UnitsString); pause(0);
710       
711       
712        % If correcting the orbit, then recorrect the horizontal center now
713        if strcmpi(QMS_Vertical.CorrectOrbit, 'yes')
714           % Correct the horizontal orbit
715           OrbitCorrection(Xoffset, BPMxFamily, BPMxDev, HCMFamily, HCMDev, 4);
716        end
717
718               
719        if strcmpi(QMS_Vertical.ModulationMethod, 'sweep')
720            % One dimensional sweep of the quadrupole
721            sleep(ExtraDelay);
722            x1(:,i) = getam(BPMxFamily, BPMxDevList);
723            y1(:,i) = getam(BPMyFamily, BPMyDevList);
724            x0(:,i) = x1(:,i);
725            y0(:,i) = y1(:,i);
726           
727            if (GetTuneFlag || strcmpi(Mode, 'Simulator')) && isfamily('TUNE')
728                QMS_Vertical.Tune1(:,i) = gettune;
729            end
730
731            setquad(QMS_Vertical, i*DelQuad*sign(QUAD0)+QUAD0, WaitFlag);
732            sleep(ExtraDelay);
733
734            % If correcting the orbit, then recorrect the horizontal center now
735            if strcmpi(QMS_Vertical.CorrectOrbit, 'yes')
736                % Correct the horizontal orbit
737                OrbitCorrection(Xoffset, BPMxFamily, BPMxDev, HCMFamily, HCMDev, 4);
738                sleep(ExtraDelay);
739            end
740
741            x2(:,i) = getam(BPMxFamily, BPMxDevList);
742            y2(:,i) = getam(BPMyFamily, BPMyDevList);
743           
744            if (GetTuneFlag || strcmpi(Mode, 'Simulator')) && isfamily('TUNE')
745                QMS_Vertical.Tune2(:,i) = gettune;
746            end
747
748        elseif strcmpi(QMS_Vertical.ModulationMethod, 'bipolar')
749            % Modulate the quadrupole
750            sleep(ExtraDelay);
751            x0(:,i) = getam(BPMxFamily, BPMxDevList);
752            y0(:,i) = getam(BPMyFamily, BPMyDevList);
753            setquad(QMS_Vertical,-DelQuad*sign(QUAD0)+QUAD0, WaitFlag);
754            sleep(ExtraDelay);
755
756            % If correcting the orbit, then recorrect the horizontal center now
757            if strcmpi(QMS_Vertical.CorrectOrbit, 'yes')
758                % Correct the horizontal orbit
759                OrbitCorrection(Xoffset, BPMxFamily, BPMxDev, HCMFamily, HCMDev, 4);
760                sleep(ExtraDelay);
761            end
762
763            x1(:,i) = getam(BPMxFamily, BPMxDevList);
764            y1(:,i) = getam(BPMyFamily, BPMyDevList);
765           
766            if (GetTuneFlag || strcmpi(Mode, 'Simulator')) && isfamily('TUNE')
767                QMS_Vertical.Tune1(:,i) = gettune;
768            end
769
770            setquad(QMS_Vertical,+DelQuad*sign(QUAD0)+QUAD0, WaitFlag);
771            sleep(ExtraDelay);
772
773            % If correcting the orbit, then recorrect the horizontal center now
774            if strcmpi(QMS_Vertical.CorrectOrbit, 'yes')
775                % Correct the horizontal orbit
776                OrbitCorrection(Xoffset, BPMxFamily, BPMxDev, HCMFamily, HCMDev, 4);
777                sleep(ExtraDelay);
778            end
779
780            x2(:,i) = getam(BPMxFamily, BPMxDevList);
781            y2(:,i) = getam(BPMyFamily, BPMyDevList);
782           
783            if (GetTuneFlag || strcmpi(Mode, 'Simulator')) && isfamily('TUNE')
784                QMS_Vertical.Tune2(:,i) = gettune;
785            end
786
787            setquad(QMS_Vertical, QUAD0, WaitFlag);
788           
789        elseif strcmpi(QMS_Vertical.ModulationMethod, 'unipolar')
790            % Modulate the quadrupole
791            sleep(ExtraDelay);
792            x1(:,i) = getam(BPMxFamily, BPMxDevList);
793            y1(:,i) = getam(BPMyFamily, BPMyDevList);
794            x0(:,i) = x1(:,i);
795            y0(:,i) = y1(:,i);
796           
797            if (GetTuneFlag || strcmpi(Mode, 'Simulator')) && isfamily('TUNE')
798                QMS_Vertical.Tune1(:,i) = gettune;
799            end
800
801            setquad(QMS_Vertical, DelQuad*sign(QUAD0)+QUAD0, WaitFlag);
802            sleep(ExtraDelay);
803
804            % If correcting the orbit, then recorrect the horizontal center now
805            if strcmpi(QMS_Vertical.CorrectOrbit, 'yes')
806                % Correct the horizontal orbit
807                OrbitCorrection(Xoffset, BPMxFamily, BPMxDev, HCMFamily, HCMDev, 4);
808                sleep(ExtraDelay);
809            end
810
811            x2(:,i) = getam(BPMxFamily, BPMxDevList);
812            y2(:,i) = getam(BPMyFamily, BPMyDevList);
813           
814            if (GetTuneFlag || strcmpi(Mode, 'Simulator')) && isfamily('TUNE')
815                QMS_Vertical.Tune2(:,i) = gettune;
816            end
817
818            setquad(QMS_Vertical, QUAD0, WaitFlag);
819        end
820       
821        DCCT(i) = getdcct;
822    end
823
824    setsp(VCMFamily, VCM0, VCMDev, -1);
825
826   
827    % Get the vertical data filename and save the data
828    % Append data and time
829    FileName = ['bba', num2str(QuadDev(1,1)), QuadFamily, num2str(QuadDev(1,2)), 'vplane'];
830    FileName = appendtimestamp(FileName, clock);
831
832    %% Append version number
833    %i=1;
834    %FileName = ['s', num2str(QuadDev(1,1)), QuadFamily, num2str(QuadDev(1,2)), 'v', num2str(i)];
835    %while exist([FileName,'.mat'], 'file')
836    %    i = i + 1;
837    %    FileName = ['s', num2str(QuadDev(1,1)), QuadFamily, num2str(QuadDev(1,2)), 'v', num2str(i)];
838    %end
839
840    QMS = QMS_Vertical;
841    QMS.QuadPlane = 2;
842
843    QMS.OldCenter = Yoffset;
844    QMS.XOffsetOld = XoffsetOld;
845    QMS.YOffsetOld = YoffsetOld;
846   
847    QMS.xstart = xstart;
848    QMS.ystart = ystart;
849    QMS.x0 = x0;
850    QMS.x1 = x1;
851    QMS.x2 = x2;
852    QMS.y0 = y0;
853    QMS.y1 = y1;
854    QMS.y2 = y2;
855    QMS.Xerr = Xerr;
856    QMS.Yerr = Yerr;
857    QMS.TimeStamp = clock;
858    QMS.DCCT = DCCT;
859    QMS.DataDescriptor = 'Quadrupole Center';
860    QMS.CreatedBy = 'quadcenter';
861
862    % Get and store the BPM status and standard deviation (to be used by the center calculation routine)
863    QMS.BPMStatus = family2status(BPMyFamily, BPMyDevList);
864    N = getbpmaverages(BPMyDevList);
865    QMS.BPMSTD = getsigma(BPMyFamily, BPMyDevList, N);
866
867   
868    % Set up figures, plot and find vertical center
869    if isempty(FigureHandle)
870        QMS = quadplot(QMS);
871    else
872        QMS = quadplot(QMS, FigureHandle);
873    end
874    drawnow;
875
876    if XYPlane==0
877        QMS2 = QMS;
878    else
879        QMS1 = QMS;
880    end
881   
882   
883    % Save the vertical data
884    if isfield(QMS_Vertical,'DataDirectory') 
885        [FinalDir, ErrorFlag] = gotodirectory(QMS_Vertical.DataDirectory);
886    end
887    QMS.DataDirectory = pwd;   
888    save(FileName, 'QMS');
889    fprintf('   Data saved to file %s in directory %s\n\n', FileName, QMS.DataDirectory);
890   
891    % Output data to log file
892    fid1 = fopen('quadcenter.log','at');
893    time=clock;
894    fprintf(fid1, '%s   %d:%d:%2.0f \n', date, time(4),time(5),time(6));
895    fprintf(fid1, 'Data saved to file %s (%s)\n', FileName, QMS.DataDirectory);
896    fprintf(fid1, '%s(%d,%d) %s(%d,%d) = %f (+/- %f) [%s]\n\n', QuadFamily, QuadDev, BPMyFamily, BPMyDev, QMS.Center, QMS.CenterSTD);
897    fclose(fid1);
898    cd(DirStart);
899
900    if (GetTuneFlag || strcmpi(Mode, 'Simulator')) && isfamily('TUNE')
901        % Print the tune information
902        fprintf('   Tune and tune difference for the 1st points in the merit function (QMS.Tune1): \n');
903        fprintf('   %8.5f', QMS.Tune1(1,:));
904        fprintf('  Horizontal\n');
905        fprintf('   %8.5f', QMS.Tune1(2,:));
906        fprintf('  Vertical\n');
907        fprintf('   ===================================================\n');
908        fprintf('   %8.5f', diff(QMS.Tune1));
909        fprintf('  Difference \n\n');
910       
911        fprintf('   Tune and tune difference for the 2nd points in the merit function (QMS.Tune2): \n');
912        fprintf('   %8.5f', QMS.Tune2(1,:));
913        fprintf('  Horizontal\n');
914        fprintf('   %8.5f', QMS.Tune2(2,:));
915        fprintf('  Vertical\n');
916        fprintf('   ===================================================\n');
917        fprintf('   %8.5f', diff(QMS.Tune2));
918        fprintf('  Difference\n\n');
919
920        dTune1 = diff(QMS.Tune1);
921        dTune2 = diff(QMS.Tune2);
922       
923        if any(sign(dTune1/dTune1(1))==-1)
924            fprintf('   Tune change sign!!!\n');           
925        end
926       
927        if any(abs(dTune1) < .025) || any(abs(dTune2) < .025)
928            fprintf('   Horizontal and vertical tunes seem too close.\n');
929        end
930    end
931end
932
933
934% Restore magnets their starting points
935setsp(HCMFamily, HCM00, HCMDev, 0);
936setsp(VCMFamily, VCM00, VCMDev, 0);
937setquad(QMS_Horizontal, QUAD0, 0);
938
939
940% Restore the MML error warning level
941setfamilydata(ErrorWarningLevel, 'ErrorWarningLevel');
942
943
944%%%%%%%%%%%%%%%%%%%%%
945% End Main Function %
946%%%%%%%%%%%%%%%%%%%%%
947
948
949
950%%%%%%%%%%%%%%%%%
951% Sub-Functions %
952%%%%%%%%%%%%%%%%%
953
954function OrbitCorrection(GoalOrbit, BPMFamily, BPMDevList, CMFamily, CMDevList, Iter)
955
956WaitFlag = -2;
957
958if nargin < 6
959    Iter = 3;
960end
961
962if size(CMDevList,1) > 1
963    % Pick the corrector based on the most effective corrector in the response matrix
964    % This routine does not handle local bumps at the moment
965    R = getrespmat(BPMFamily, BPMDevList, CMFamily, [], 'Struct', 'Physics');
966    [i, iNotFound] = findrowindex(BPMDevList, R.Monitor.DeviceList);
967    m = R.Data(i,:);
968    [MaxValue, j] = max(abs(m));
969    CMDevList = R.Actuator.DeviceList(j,:);
970end
971
972s = getrespmat(BPMFamily, BPMDevList, CMFamily, CMDevList);
973if any(any(isnan(s)))
974    error('Response matrix has a NaN');
975end
976
977
978for i = 1:Iter
979    x = getam(BPMFamily, BPMDevList) - GoalOrbit;
980   
981    CorrectorSP = -(x./s);
982    CorrectorSP = CorrectorSP(:);
983   
984    % Check limits
985    MinSP = minsp(CMFamily, CMDevList);
986    MaxSP = maxsp(CMFamily, CMDevList);
987    if any(getsp(CMFamily,CMDevList)+CorrectorSP > MaxSP-5)
988        fprintf('   Orbit not corrected because a maximum power supply limit would have been exceeded!\n');
989        return;
990    end
991    if any(getsp(CMFamily,CMDevList)+CorrectorSP < MinSP+5)
992        fprintf('   Orbit not corrected because a minimum power supply limit would have been exceeded!\n');
993        return;
994    end
995   
996    stepsp(CMFamily, CorrectorSP, CMDevList, WaitFlag);
997   
998    %x = getam(BPMFamily, BPMDevList) - GoalOrbit
999end
1000
1001
1002
1003
1004% function AM = getquad(QMS)
1005% % AM = getquad(QMS)
1006%
1007% QuadFamily = QMS.QuadFamily;
1008% QuadDev = QMS.QuadDev;
1009%
1010% % Check operational mode
1011% %mode = getfamilydata(QuadFamily, 'Setpoint', 'Mode', QuadDev);
1012%
1013% AM = getam(QuadFamily, QuadDev);
1014
1015
1016% function setquad(QMS, QuadSetpoint, WaitFlag)
1017% % setquad(QMS, QuadSetpoint, WaitFlag)
1018%     
1019% if nargin < 3
1020%     WaitFlag = -2;
1021% end
1022%
1023% QuadFamily = QMS.QuadFamily;
1024% QuadDev = QMS.QuadDev;
1025%
1026% setsp(QuadFamily, QuadSetpoint, QuadDev, WaitFlag);
1027
1028
1029
Note: See TracBrowser for help on using the repository browser.