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