source: MML/trunk/mml/rmdisp.m @ 4

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

Initial import--MML version from SOLEIL@2013

File size: 12.9 KB
Line 
1function [DeltaRF, BPM, c, DispOrbit] = rmdisp(varargin)
2%RMDISP - Removes the portion of the orbit that correlates with the dispersion
3%  [DeltaRF, OrbitRM, c, DispOrbit] = rmdisp(BPMFamily, Orbit, BPMList, Dispersion)
4%  [DeltaRF, OrbitRM, c, DispOrbit] = rmdisp(BPMStruct, Dispersion)
5%
6%  INPUTS
7%  1. BPMFamily - Family name {Default: 'BPMx'}
8%     BPMStruct - BPM data structure.  When using data structures, the orbit and
9%                 BPMList are in the .Data and .DeviceList fields, respectively.
10%  2. Orbit - Input orbit  {Default or empty: get the present orbit}
11%  3. BPMList - Device or element list of BPMs  {Default or empty: all}
12%  4  FLAGS - 'FitMean' or 'FitDispersionOnly' {Default} - Include or don't include the mean in the fit
13%             'MeasDisp' - Measure the dispersion
14%             'ModelDisp' - Calculate the model dispersion
15%             'GoldenDisp' - Use the golden dispersion  {Default}
16%             'Display' - Plot orbit information {Default: no display unless there are no outputs}
17%             'NoDisplay' - No plot
18%             'SetRF' - Sets the RF frequency to the new value (prompts to check the value if 'Display' is on)
19%             'NoSetRF' - Don't set the RF frequency
20%             (the usual Units and Mode flags: 'Online', 'Model', 'Manual', 'Hardware', 'Physics', etc.)
21%  5. Dispersion - Optional input to specify the dispersion
22%
23%  OUTPUTS
24%  1. DeltaRF - Change in RF frequency required to remove the dispersion component of
25%               the orbit.  The units are the in RF frequency units used by getrf/setrf.
26%               If DeltaRF = [], the units of dispersion or RF frequency were not unknown.  In
27%               which case use c, output 3, to get the change in RF frequency.
28%  2. OrbitRM - Estimated orbit with the dispersion orbit removed
29%  3. c - fit coefficient,  OrbitRM = Orbit - c * Dispersion
30%         c converts to RF frequency change but it depends on the units for the
31%         orbit and dispersion.  For instance, if Orbit is in [mm] and Dispersion is
32%         in [mm/MHz], then c is in MHz.  If Orbit is in [m] and Dispersion is in
33%         [meter/(dp/p)], then c is energy shift (DeltaRF = -c*mcf*RF [Hz]). 
34%         To correct the orbit, change the RF frequency by negative of the frequency
35%         change determined by the c coefficient.
36%  3. DispOrbit - Dispersion orbit used in the calculation
37%
38%  NOTES
39%  1. It is unclear to the author if it is better to fit the mean or not.  If the
40%     BPM offsets are not known very well then fitting the mean may be better.  That way
41%     the dispersion is not used as a way to change the orbit mean (beyond
42%     the mean change due to the shape and sampling of the dispersion function).
43%  2. When fitting the mean the RF frequency change is only based only the dispersion
44%     fit coefficient.
45%  3. It is best to use structure inputs, since the units are in the structure.  Hence,
46%     the DeltaRF can be determined.
47%
48%  See also setorbit findrf plotcm
49%
50%  Written by Greg Portmann
51
52
53% Option to fit the mean as well as the dispersion
54% FitMeanFlag = 0 -> only fit the dispersion
55% FitMeanFlag = 1 -> fit both the mean and dispersion but only remove the
56%                    dispersion coefficient from the orbit
57% It can be good fit the mean (at least if BPM offsets are not known),
58% so that the dispersion is not used as a way to change the orbit mean (beyond
59% the mean change due to the shape and sampling of the dispersion function).
60% When using difference orbits, I wouldn't fit the mean.
61% Note: fitting the mean and dispersion together is different from removing
62% the mean then fitting the dispersion.
63FitMeanFlag = 0;
64
65
66%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
67% Input parsing and checking %
68%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
69
70if nargout == 0
71    DisplayFlag = 1;
72else
73    DisplayFlag = 0;
74end
75ChangeRFFlag = 0;
76DispFlag = 'GoldenDisp';
77StructOutputFlag = 0;
78NumericOutputFlag = 0;
79DispOrbitStruct = [];
80InputFlags = {};
81for i = length(varargin):-1:1
82    if isstruct(varargin{i})
83        % Ignor structures
84    elseif iscell(varargin{i})
85        % Ignor cells
86    elseif strcmpi(varargin{i},'SetRF')
87        ChangeRFFlag = 1;
88        varargin(i) = [];
89    elseif strcmpi(varargin{i},'NoSetRF')
90        ChangeRFFlag = 0;
91        varargin(i) = [];
92    elseif strcmpi(varargin{i},'Display')
93        DisplayFlag = 1;
94        varargin(i) = [];
95    elseif strcmpi(varargin{i},'NoDisplay')
96        DisplayFlag = 0;
97        varargin(i) = [];
98    elseif strcmpi(varargin{i},'ModelDisp')
99        DispFlag = varargin{i};
100        varargin(i) = [];
101    elseif strcmpi(varargin{i},'MeasDisp')
102        DispFlag = varargin{i};
103        varargin(i) = [];
104    elseif strcmpi(varargin{i},'FitMean')
105        FitMeanFlag = 1;
106        varargin(i) = [];
107    elseif strcmpi(varargin{i},'FitDispersionOnly')
108        FitMeanFlag = 0;
109        varargin(i) = [];
110    elseif strcmpi(varargin{i},'GoldenDisp')
111        DispFlag = varargin{i};
112        varargin(i) = [];
113    elseif strcmpi(varargin{i},'simulator') | strcmpi(varargin{i},'model')
114        ModeFlag = 'SIMULATOR';
115        InputFlags = [InputFlags varargin(i)];
116        varargin(i) = [];
117    elseif strcmpi(varargin{i},'Online')
118        ModeFlag = 'Online';
119        InputFlags = [InputFlags varargin(i)];
120        varargin(i) = [];
121    elseif strcmpi(varargin{i},'Manual')
122        ModeFlag = 'Manual';
123        InputFlags = [InputFlags varargin(i)];
124        varargin(i) = [];
125    elseif strcmpi(varargin{i},'physics')
126        UnitsFlag = 'Physics';
127        InputFlags = [InputFlags varargin(i)];
128        varargin(i) = [];
129    elseif strcmpi(varargin{i},'hardware')
130        UnitsFlag = 'Hardware';
131        InputFlags = [InputFlags varargin(i)];
132        varargin(i) = [];
133    elseif strcmpi(varargin{i},'struct')
134        StructOutputFlag = 1;
135        varargin(i) = [];
136    elseif strcmpi(varargin{i},'numeric')
137        NumericOutputFlag = 1;
138        StructOutputFlag = 0;
139        varargin(i) = [];
140    end
141end
142
143if length(varargin) < 1
144    varargin = {'BPMx'};
145end
146
147if isstruct(varargin{1})
148    BPM = varargin{1};
149    if ~isfamily(BPM)
150        error(sprintf('%s is not a family'), BPM.FamilyName);
151    end
152    if length(varargin) >= 2
153        % Use dispersion for the input line
154        DispOrbitStruct = varargin{2};
155    end
156
157    % Only change StructOutputFlag if 'numeric' is not on the input line
158    if ~NumericOutputFlag
159        StructOutputFlag = 1;
160    end
161else
162    if ischar(varargin{1})
163        BPM.FamilyName = varargin{1};
164    else
165        error('First input must be a structure or FamilyName');
166    end
167    if ~isfamily(BPM.FamilyName)
168        error(sprintf('%s is not a BPM family', BPM.FamilyName));
169    end
170    if length(varargin) >= 2
171        BPM.Data = varargin{2};
172    else
173        BPM = getam(BPM.FamilyName, 'Struct', InputFlags{:});
174    end
175    if length(varargin) >= 3
176        BPM.DeviceList = varargin{3};
177    elseif ~isfield(BPM, 'DeviceList')
178        BPM.DeviceList = getlist(BPM.FamilyName);
179    end
180    if length(varargin) >= 4
181        % Use dispersion for the input line
182        DispOrbitStruct = varargin{4};
183    end
184end
185
186
187%%%%%%%%%%%%%%%%%%
188% Get Dispersion %
189%%%%%%%%%%%%%%%%%%
190DispUnitsString = '';
191if isempty(DispOrbitStruct)
192    if strcmpi(DispFlag,'ModelDisp')
193        DispOrbitStruct = measdisp(BPM, 'Struct', 'Model', InputFlags{:});
194        DispUnitsString = DispOrbitStruct.UnitsString;
195    elseif strcmpi(DispFlag,'MeasDisp')
196        DispOrbitStruct = measdisp(BPM, 'Struct', InputFlags{:});
197        DispUnitsString = DispOrbitStruct.UnitsString;
198    elseif strcmpi(DispFlag,'GoldenDisp')
199        DispOrbitStruct = getdisp(BPM.FamilyName, BPM.DeviceList, 'Struct');
200        DispUnitsString = DispOrbitStruct.UnitsString;
201    end
202end
203if isempty(DispOrbitStruct)
204    error('Did not find or generate a proper dispersion function');
205end
206
207% If dispersion is a structure, just use the .Data field
208if isstruct(DispOrbitStruct)
209    DispOrbit = DispOrbitStruct.Data;
210else
211    DispOrbit = DispOrbitStruct;   
212end
213
214
215%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
216% Fit the orbit into the dispersion function %
217%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
218
219% Dot product of dispersion and the orbit can be used
220% to find the RF frequency but to find the orbit which best
221% correlates to the dispersion use a least squares fit
222% c = BPM.Data' * DispOrbit; 
223
224BPMDataOld = BPM.Data;
225if FitMeanFlag
226    % Fit the mean and the dispersion orbit
227    X = [ones(size(DispOrbit)) DispOrbit];
228    cfit = X \ BPM.Data;
229    c = cfit(2);
230    %BPM.Data = BPM.Data - X * c;
231else
232    % Fit the dispersion orbit
233    cfit = DispOrbit \ BPM.Data;
234    c = cfit;
235end
236
237%BPM.Data = BPM.Data - X * c;
238BPM.Data = BPM.Data - DispOrbit * c;
239
240
241% Comput the change in RF frequency
242% Units are a big pain the neck when it comes to determining the actual RF change
243% Note: this section will depend a little on how the UnitsString is setup
244% c units = BPM units / Dispersion units
245RF0 = getrf('Struct', InputFlags{:});
246DeltaRF = [];           
247if ~isfield(BPM,'UnitsString')
248    [units, unitsstring] = getunits(BPM, 'Monitor');
249    BPM.UnitsString = unitsstring;  % Hopefully this is true
250    %if DisplayFlag
251    %    fprintf('   BPM units are defined.  Assuming units are %s.\n', unitsstring);
252    %end
253end
254if ~isempty(BPM.UnitsString) & ~isempty(DispUnitsString)
255    % May need to scale by the orbit units
256    if strfind(lower(BPM.UnitsString), 'mm') | strfind(lower(BPM.UnitsString), 'millimeter') | strfind(lower(BPM.UnitsString), 'millimeters')
257        % BPM is in mm
258        if strfind(DispUnitsString, 'mm') | strfind(DispUnitsString, 'millimeter') | strfind(DispUnitsString, 'millimeters')
259            % Dispersion is in mm, hence the units are ok
260        elseif strfind(DispUnitsString, 'm') | strfind(DispUnitsString, 'meter') | strfind(DispUnitsString, 'meters') 
261            % Dispersion is in meters
262            c = c / 1000;
263        else
264            DeltaRF = [];           
265        end
266    elseif strfind(lower(BPM.UnitsString), 'm') | strfind(lower(BPM.UnitsString), 'meter') | strfind(lower(BPM.UnitsString), 'meter')
267        % BPM is in meters
268        if strfind(lower(DispUnitsString), 'mm') | strfind(lower(DispUnitsString), 'millimeter') | strfind(lower(DispUnitsString), 'millimeters')
269            % Dispersion is in mm, hence the units are ok
270            c = c * 1000;
271        elseif strfind(lower(DispUnitsString), 'm') | strfind(lower(DispUnitsString), 'meter') | strfind(lower(DispUnitsString), 'meters')
272            % Dispersion is in meters, hence the units are ok
273        else
274            DeltaRF = [];           
275        end
276    end
277   
278    % Change units to the same as getrf
279    if strfind(lower(DispUnitsString), 'mhz')
280        if strcmpi(RF0.UnitsString, 'MHz')
281            DeltaRF = c;        % c is MHz, DeltaRF is MHz
282        elseif strcmpi(RF0.UnitsString, 'Hz')
283            DeltaRF = c * 1e6;  % c is MHz, DeltaRF is Hz
284        else
285            DeltaRF = [];           
286        end
287    elseif strfind(lower(DispUnitsString), 'hz')
288        if strcmpi(RF0.UnitsString, 'MHz')
289            DeltaRF = c / 1e6;  % c is Hz, DeltaRF is MHz
290        elseif strcmpi(RF0.UnitsString, 'Hz')
291            DeltaRF = c;        % c is Hz, DeltaRF is Hz
292        else
293            DeltaRF = [];           
294        end
295    elseif strfind(lower(DispUnitsString), 'dp/p')
296        DeltaRF = c * getmcf * RF0.Data;  % Units same as RF0
297    else
298        DeltaRF = [];
299    end
300
301    % Return the change in RF required to remove the orbit error
302    DeltaRF = -DeltaRF;
303else
304    DeltaRF = -c;   
305end
306
307
308%%%%%%%%%%%%%%%%%%%%%%
309% Output and display %
310%%%%%%%%%%%%%%%%%%%%%%
311if DisplayFlag
312    spos = getspos(BPM);
313    clf reset
314    subplot(2,1,1);
315    plot(spos, BPMDataOld, 'r', spos, BPM.Data, 'b');
316    grid on
317    xlabel('Position [Meters]');
318    if isfield(BPM,'UnitsString')
319        ylabel(sprintf('%s [%s]', BPM.FamilyName, BPM.UnitsString));
320    else
321        ylabel(sprintf('%s', BPM.FamilyName));
322    end
323    legend('Starting Orbit','Dispersion Removed')
324    if length(cfit) == 2
325        title(sprintf('%g + %g * Dispersion',cfit(1), cfit(2)));
326    else
327        title(sprintf('%g * Dispersion',cfit(1)));
328    end
329   
330    subplot(2,1,2);
331    %plot(spos, X * c, 'b');
332    plot(spos, DispOrbit * c, 'b');
333    grid on
334    xlabel('Position [Meters]');
335    if isfield(BPM,'UnitsString')
336        ylabel(sprintf('Orbit Removed [%s]',BPM.UnitsString));
337    else
338        ylabel(sprintf('Orbit Removed'));
339    end
340end
341
342
343if ~StructOutputFlag
344    BPM = BPM.Data;
345end
346
347
348% Set the RF frequency
349if ChangeRFFlag
350    if ~isempty(DeltaRF)
351        if DisplayFlag
352            answer = inputdlg({strvcat(strvcat(sprintf('Recommend change in RF is %g %s', DeltaRF, RF0.UnitsString), '  '), 'Change the RF frequency?')},'RMDISP',1,{sprintf('%g',DeltaRF)});
353            if isempty(answer)
354                fprintf('   No change was made to the RF frequency\n');
355                return
356            end
357            DeltaRF = str2num(answer{1});
358        end
359        steprf(DeltaRF, InputFlags{:});
360    else
361        error('RF frequency not changed because of a problem converting the units for dispersion and orbit to RF frequency');
362    end
363end
364
Note: See TracBrowser for help on using the repository browser.