source: MML/trunk/applications/loco/calclocochi2.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: 12.6 KB
Line 
1function ChiSquare = calclocochi2(LocoModel, LocoMeasData, BPMData, CMData, FitParameters, LocoFlags, RINGData)
2%CALCLOCOCHI2 - Calculate the contribution to chi^2 of each fit parameter in LOCO
3%  ChiSquare = calclocochi2(LocoModel, LocoMeasData, BPMData, CMData, FitParameters, LocoFlags, RINGData)
4%  ChiSquare = calclocochi2(LOCOFileName)
5
6
7% Input #1 can be a LOCO file
8if ischar(LocoModel)
9    load(LocoModel);
10end
11
12
13% Get the flags
14LocoParams = FitParameters.Params;
15LocoValues = FitParameters.Values;
16LocoDeltas = FitParameters.Deltas;
17SVmethod             = LocoFlags.SVmethod;
18AutoCorrectDeltaFlag = LocoFlags.AutoCorrectDelta;
19CouplingFlag         = LocoFlags.Coupling;
20NormalizeFlag        = LocoFlags.Normalize;
21OutlierFactor        = LocoFlags.OutlierFactor;
22
23% UNITS CONVERSIONS (to be combatible with tracking code)
24% Convert corrector kicks used in the response matrix to radians
25CMData.HCMKicks = CMData.HCMKicks(:) / 1000;   % milliradian to radians (column vector)
26CMData.VCMKicks = CMData.VCMKicks(:) / 1000;   % milliradian to radians (column vector)
27
28% Convert the measured response matrix to meters
29LocoMeasData.M = LocoMeasData.M / 1000;
30
31% Convert the BPMSTD to meters and make the same size as a response matrix
32LocoMeasData.BPMSTD = LocoMeasData.BPMSTD / 1000;    % mm to meters
33Mstd = LocoMeasData.BPMSTD * ones(1,size(LocoMeasData.M,2));
34
35% Convert orbit for "dispersion" in meters in column vector format
36LocoMeasData.Eta = LocoMeasData.Eta(:) / 1000;       % mm to meters
37% END UNITS CONVERTSION
38
39% Use the entire family of BPMs in the model response matrix, then index later (not much difference computationally)
40BPMIndexShortX = BPMData.HBPMIndex(BPMData.HBPMGoodDataIndex);
41BPMIndexShortY = length(BPMData.BPMIndex)+BPMData.VBPMIndex(BPMData.VBPMGoodDataIndex);
42BPMIndexShort = [BPMIndexShortX(:)' BPMIndexShortY(:)'];
43NHBPM = length(BPMData.HBPMGoodDataIndex);
44NVBPM = length(BPMData.VBPMGoodDataIndex);
45NBPM  = NHBPM + NVBPM;
46NHCM = length(CMData.HCMGoodDataIndex);
47NVCM = length(CMData.VCMGoodDataIndex);
48
49
50% Remove unwanted data from the Mmeas and Mstd
51Mmeas = LocoMeasData.M([BPMData.HBPMGoodDataIndex length(BPMData.HBPMIndex)+BPMData.VBPMGoodDataIndex], [CMData.HCMGoodDataIndex length(CMData.HCMIndex)+CMData.VCMGoodDataIndex]);
52Mstd  =           Mstd([BPMData.HBPMGoodDataIndex length(BPMData.HBPMIndex)+BPMData.VBPMGoodDataIndex], [CMData.HCMGoodDataIndex length(CMData.HCMIndex)+CMData.VCMGoodDataIndex]);
53
54% If including dispersion then Mstd and Mmeas must include disperion term
55if strcmpi((LocoFlags.Dispersion),'yes')
56    Xstd = LocoMeasData.BPMSTD(BPMData.HBPMGoodDataIndex);
57    Ystd = LocoMeasData.BPMSTD(length(BPMData.HBPMIndex)+BPMData.VBPMGoodDataIndex);
58   
59    if isempty(LocoMeasData.Eta)
60        error('Measured dispersion (LocoMeasData.Eta) can not be empty when including dispersion');
61    end
62    EtaX = LocoMeasData.Eta(BPMData.HBPMGoodDataIndex);
63    EtaY = LocoMeasData.Eta(length(BPMData.HBPMIndex)+BPMData.VBPMGoodDataIndex);
64   
65    LocoFlags.HorizontalDispersionWeight = abs(LocoFlags.HorizontalDispersionWeight);
66    LocoFlags.VerticalDispersionWeight   = abs(LocoFlags.VerticalDispersionWeight);
67
68    % Should remove the dispersion if both weights are zero
69    if LocoFlags.HorizontalDispersionWeight == 0
70        LocoFlags.HorizontalDispersionWeight = eps;
71    end
72    if LocoFlags.VerticalDispersionWeight == 0
73        LocoFlags.VerticalDispersionWeight = eps;
74    end
75   
76    % Weight the dispersion
77    Mstd  = [Mstd  [Xstd/LocoFlags.HorizontalDispersionWeight; Ystd/LocoFlags.VerticalDispersionWeight]];
78    Mmeas = [Mmeas [EtaX; EtaY]];
79end
80
81
82% Convert to a column vector
83Mstd  = Mstd(:);
84Mmeas = Mmeas(:);
85
86
87% Build the corrector magnet data structures to be used with locoresponsematrix
88CMDataRM.FamName = CMData.FamName;
89CMDataRM.HCMIndex = CMData.HCMIndex(CMData.HCMGoodDataIndex);
90CMDataRM.VCMIndex = CMData.VCMIndex(CMData.VCMGoodDataIndex);
91CMDataRM.HCMKicks = CMData.HCMKicks(CMData.HCMGoodDataIndex);
92CMDataRM.VCMKicks = CMData.VCMKicks(CMData.VCMGoodDataIndex);
93CMDataRM.HCMCoupling = CMData.HCMCoupling(CMData.HCMGoodDataIndex);
94CMDataRM.VCMCoupling = CMData.VCMCoupling(CMData.VCMGoodDataIndex);
95CMDataRM.HCMEnergyShift = CMData.HCMEnergyShift(CMData.HCMGoodDataIndex);
96CMDataRM.VCMEnergyShift = CMData.VCMEnergyShift(CMData.VCMGoodDataIndex);
97
98% Compute the new model response matrix with dispersion for saving
99%fprintf('   Computing final response matrix (after fit) (%s, %s) ... ', LocoFlags.ResponseMatrixCalculator, LocoFlags.ClosedOrbitType); tic
100CMDataRM.HCMKicks    = CMData.HCMKicks(CMData.HCMGoodDataIndex);
101CMDataRM.VCMKicks    = CMData.VCMKicks(CMData.VCMGoodDataIndex);
102CMDataRM.HCMCoupling = CMData.HCMCoupling(CMData.HCMGoodDataIndex);
103CMDataRM.VCMCoupling = CMData.VCMCoupling(CMData.VCMGoodDataIndex);
104warning off;
105lastwarn('');
106
107%modify RINGData
108LocoValues = LocoValues(:);      % Force a column vector
109for i = 1:length(LocoParams)
110    % Compute the response matrix with the parameter change
111        RINGData = locosetlatticeparam(RINGData, LocoParams{i}, LocoValues(i));
112end
113
114if isempty(FitParameters.DeltaRF)
115    Mmodel = locoresponsematrix(RINGData, BPMData, CMDataRM, LocoFlags);
116else
117    Mmodel = locoresponsematrix(RINGData, BPMData, CMDataRM, LocoFlags, 'RF', FitParameters.DeltaRF);
118end
119warning on;
120%fprintf('%f seconds. \n',toc);
121% if ~isempty(lastwarn)
122%     fprintf('\n   Warning computing the final response matrix:\n         %s\n', lastwarn);
123%     fprintf(  '   Check the final values of the fits to make sure they are in a reasonable range for\n');
124%     fprintf(  '   this accelerator.  Check the input data and/or reduce the number of singular values.\n\n');
125% end
126
127% To remove the off-diagonal part of the A matrix find the index vector, iNoCoupling, of rows to keep
128if strcmpi((CouplingFlag),'no')
129    CF = [ ones(NHBPM,NHCM) zeros(NHBPM,NVCM);
130          zeros(NVBPM,NHCM)  ones(NVBPM,NVCM)];
131
132    % Keep the dispersion
133    if strcmpi((LocoFlags.Dispersion),'yes')
134        % Keep the horizontal and vertical part of the "dispersion" orbit
135        CF = [CF [2*ones(NHBPM,1); 3*ones(NVBPM,1)]];    % Make zeros to ignor dispersion
136    end
137       
138    CF = CF(:);
139    iNoCoupling = find(CF > 0);               % Rows of A to keep when ignoring coupling
140    %iHorizontalDispersion = find(CF == 2);   % Rows of A corresponding to horizontal dispersion
141    %iVerticalDispersion = find(CF == 3);     % Rows of A corresponding to vertical dispersion
142    clear CF
143else
144    if strcmpi((LocoFlags.Dispersion),'yes')
145        iNoCoupling = (1:(NVBPM+NHBPM)*(NHCM+NVCM+1))';
146    else
147        iNoCoupling = (1:(NVBPM+NHBPM)*(NHCM+NVCM))';
148    end
149end
150
151% Rotate Mmodel and remove BPMs not in the measured response matrix
152C11 = ones(length(BPMData.BPMIndex),1);
153C11(BPMData.HBPMIndex(BPMData.HBPMGoodDataIndex)) = BPMData.HBPMGain(BPMData.HBPMGoodDataIndex);
154
155C12 = zeros(length(BPMData.BPMIndex),1);
156C12(BPMData.HBPMIndex(BPMData.HBPMGoodDataIndex)) = BPMData.HBPMCoupling(BPMData.HBPMGoodDataIndex);
157
158C21 = zeros(length(BPMData.BPMIndex),1);
159C21(BPMData.VBPMIndex(BPMData.VBPMGoodDataIndex)) = BPMData.VBPMCoupling(BPMData.VBPMGoodDataIndex);
160
161C22 = ones(length(BPMData.BPMIndex),1);
162C22(BPMData.VBPMIndex(BPMData.VBPMGoodDataIndex)) = BPMData.VBPMGain(BPMData.VBPMGoodDataIndex);
163
164C = [diag(C11) diag(C12)
165     diag(C21) diag(C22)];
166clear C11 C12 C21 C22 
167
168Mmodel = C * Mmodel;
169Mmodel = Mmodel(BPMIndexShort, :);
170
171
172% Compute chi-squared based on new model
173Mmeas = LocoMeasData.M;
174Mmeas = Mmeas([BPMData.HBPMGoodDataIndex length(BPMData.HBPMIndex)+BPMData.VBPMGoodDataIndex], [CMData.HCMGoodDataIndex length(CMData.HCMIndex)+CMData.VCMGoodDataIndex]);
175
176Mstd = LocoMeasData.BPMSTD * ones(1,size(LocoMeasData.M,2));
177Mstd = Mstd ([BPMData.HBPMGoodDataIndex length(BPMData.HBPMIndex)+BPMData.VBPMGoodDataIndex], [CMData.HCMGoodDataIndex length(CMData.HCMIndex)+CMData.VCMGoodDataIndex]);
178
179Xstd = LocoMeasData.BPMSTD(BPMData.HBPMGoodDataIndex);
180Ystd = LocoMeasData.BPMSTD(length(BPMData.HBPMIndex)+BPMData.VBPMGoodDataIndex);
181
182
183% When using the fixed momentum response matrix calculator, the merit function becomes:
184%              Merit = Mmeas_ij - Mmod_ij - Dp/p_j * eta_i
185%              where eta_i is the measured eta (not the model eta)
186% This is done by changing Mmodel to (Mmodel_ij + Dp/p_j * eta_i)
187%if strcmpi((CMData.FitHCMEnergyShift),'yes') | strcmpi((CMData.FitVCMEnergyShift),'yes')   
188if strcmpi((LocoFlags.ClosedOrbitType), 'fixedmomentum')
189    HCMEnergyShift = CMData.HCMEnergyShift(CMData.HCMGoodDataIndex);
190    VCMEnergyShift = CMData.VCMEnergyShift(CMData.VCMGoodDataIndex);
191   
192    if ~exist('AlphaMCF')
193        AlphaMCF = locomcf(RINGData);
194        EtaXmcf = -AlphaMCF * LocoMeasData.RF * LocoMeasData.Eta(BPMData.HBPMGoodDataIndex) / LocoMeasData.DeltaRF;
195        EtaYmcf = -AlphaMCF * LocoMeasData.RF * LocoMeasData.Eta(length(BPMData.HBPMIndex)+BPMData.VBPMGoodDataIndex) / LocoMeasData.DeltaRF;
196    end
197
198    for i = 1:length(HCMEnergyShift)
199        Mmodel(:,i) = Mmodel(:,i) + HCMEnergyShift(i) * [EtaXmcf; EtaYmcf];
200    end
201   
202    for i = 1:length(VCMEnergyShift)
203        Mmodel(:,NHCM+i) = Mmodel(:,NHCM+i) + VCMEnergyShift(i) * [EtaXmcf; EtaYmcf];
204    end
205end
206
207Mstd  = Mstd(:);
208Mmeas = Mmeas(:);
209if strcmpi((LocoFlags.Dispersion),'yes') 
210    EtaX = LocoMeasData.Eta(BPMData.HBPMGoodDataIndex);
211    EtaY = LocoMeasData.Eta(length(BPMData.HBPMIndex)+BPMData.VBPMGoodDataIndex);
212   
213    Mstd  = [Mstd;  [Xstd; Ystd]];
214    Mmeas = [Mmeas; [EtaX; EtaY]];
215else
216    if ~isempty(FitParameters.DeltaRF)
217        Mmodel = Mmodel(:,1:end-1);
218    end
219end
220Mmodel = Mmodel(:);
221
222% Combine the Mmodel outliers and the Eta outliers
223if strcmpi((LocoFlags.Dispersion),'yes')
224    iOutliers = [LocoModel.OutlierIndex, LocoModel.EtaOutlierIndex + ((NHBPM+NVBPM)*(NHCM+NVCM))];
225else
226    iOutliers = LocoModel.OutlierIndex;
227end
228
229% Outliers are referenced to the coupled model
230% Mark the outliers with NaN
231Mmeas(iOutliers)  = NaN;
232Mmodel(iOutliers) = NaN;
233Mstd(iOutliers)   = NaN;
234
235% Remove coupling rows
236if strcmpi((CouplingFlag),'no')
237    Mmodel = Mmodel(iNoCoupling);
238    Mmeas = Mmeas(iNoCoupling);
239    Mstd = Mstd(iNoCoupling);
240end
241
242% Remove the outliers
243Mmeas(find(isnan(Mmeas))) = [];
244Mmodel(find(isnan(Mmodel))) = [];
245Mstd(find(isnan(Mstd))) = [];
246
247
248NumberOfFitParameters = 0;
249%count the number of fit paramters
250% Horizontal BPM gains
251if strcmpi((BPMData.FitGains),'yes')
252    NumberOfFitParameters = NumberOfFitParameters + length(BPMData.HBPMGoodDataIndex);
253end
254
255% Horizontal BPM coupling
256if strcmpi((BPMData.FitCoupling),'yes')
257    NumberOfFitParameters = NumberOfFitParameters + length(BPMData.HBPMGoodDataIndex);
258end
259
260% Vertical BPM coupling
261if strcmpi((BPMData.FitCoupling),'yes')
262   NumberOfFitParameters = NumberOfFitParameters + length(BPMData.VBPMGoodDataIndex);
263end
264
265% Vertical BPM gains
266if strcmpi((BPMData.FitGains),'yes')
267    NumberOfFitParameters = NumberOfFitParameters + length(BPMData.VBPMGoodDataIndex);
268end
269
270% Corrector magnet gains
271if strcmpi((CMData.FitKicks),'yes')
272    NumberOfFitParameters = NumberOfFitParameters + length(CMData.HCMGoodDataIndex);
273end
274
275if strcmpi((CMData.FitKicks),'yes')
276   NumberOfFitParameters = NumberOfFitParameters + length(CMData.VCMGoodDataIndex);
277end
278
279% Corrector magnet coupling
280if strcmpi((CMData.FitCoupling),'yes')   
281    NumberOfFitParameters = NumberOfFitParameters + length(CMData.HCMGoodDataIndex);
282end
283
284if strcmpi((CMData.FitCoupling),'yes')   
285    NumberOfFitParameters = NumberOfFitParameters + length(CMData.VCMGoodDataIndex);
286end
287
288% Corrector magnet energy shifts
289if strcmpi((CMData.FitHCMEnergyShift),'yes')
290    NumberOfFitParameters = NumberOfFitParameters + length(CMData.HCMGoodDataIndex);
291end
292if strcmpi((CMData.FitVCMEnergyShift),'yes')
293    NumberOfFitParameters = NumberOfFitParameters + length(CMData.VCMGoodDataIndex);
294end
295
296% RF Frequency parameter fit
297if strcmpi((FitParameters.FitRFFrequency),'yes')
298    NumberOfFitParameters = NumberOfFitParameters + 1;
299end
300
301% The rest of the parameter fits
302NumberOfFitParameters = NumberOfFitParameters + length(FitParameters.Values);
303
304
305%ChiSquare = sum(((Mmeas - Mmodel) ./ Mstd) .^ 2) / length(Mstd);
306ChiSquare = sum(((Mmeas - Mmodel) ./ Mstd) .^ 2) / (length(Mstd)-NumberOfFitParameters);   % mean e'*e = sigma*(n-k)
307% fprintf('   Chi-square/D.O.F. = %f (N=%d, K=%d) (computed from final response matrix)\n\n', ChiSquare, length(Mstd), NumberOfFitParameters);
308LocoModel.ChiSquare = ChiSquare;
309
310
311% Unit conversions (back to LOCO units)
312CMData.HCMKicks = 1000*CMData.HCMKicks;        % radian to milliradians
313CMData.VCMKicks = 1000*CMData.VCMKicks;        % radian to milliradians
314CMData.HCMKicksSTD = 1000*CMData.HCMKicksSTD;  % radian to milliradians
315CMData.VCMKicksSTD = 1000*CMData.VCMKicksSTD;  % radian to milliradians
316LocoModel.M   = 1000*LocoModel.M;              % meters to millimeters
317LocoModel.Eta = 1000*LocoModel.Eta;            % meters to millimeters
Note: See TracBrowser for help on using the repository browser.