0001 function [QMS, WarningString] = quadplotphysics(Input1, FigureHandle, sigmaBPM)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 MinSlopeFraction = .25;
0035
0036
0037 CenterOutlierFactor = 1;
0038
0039
0040 QMS = [];
0041 WarningString = '';
0042
0043
0044
0045 try
0046 if nargin == 0
0047 [FileName, PathName] = uigetfile('*.mat', 'Select a Quadrupole Center File', [getfamilydata('Directory','DataRoot'), 'QMS', filesep]);
0048 if ~isstr(FileName)
0049 return
0050 else
0051 load([PathName,FileName]);
0052 end
0053 else
0054 if isempty(Input1)
0055 [FileName, PathName] = uigetfile('*.mat', 'Select a Quadrupole Center File', [getfamilydata('Directory','DataRoot'), 'QMS', filesep]);
0056 if ~isstr(FileName)
0057 return
0058 else
0059 load([PathName,FileName]);
0060 end
0061 elseif isstr(Input1)
0062 FileName = Input1;
0063 load(FileName);
0064 else
0065 QMS = Input1;
0066 FileName = [];
0067 end
0068 end
0069 catch
0070 error('Problem getting input data');
0071 end
0072 if nargin < 2
0073 FigureHandle = [];
0074 end
0075
0076
0077 QMS.QuadraticFit = 0;
0078
0079 QuadraticFit = QMS.QuadraticFit;
0080 OutlierFactor = QMS.OutlierFactor;
0081
0082
0083 if nargin < 3
0084
0085 if isfield(QMS, 'BPMSTD')
0086 sigmaBPM = QMS.BPMSTD;
0087 else
0088 sigmaBPM = inf;
0089 end
0090 end
0091 if isempty(sigmaBPM)
0092 sigmaBPM = inf;
0093 end
0094 if isnan(sigmaBPM) | isinf(sigmaBPM)
0095 sigmaBPM = inf;
0096 fprintf(' WARNING: BPM standard deviation is unknown, hence there is no BPM outlier condition.\n');
0097 end
0098 sigmaBPM = sigmaBPM(:);
0099 QMS.BPMSTD = sigmaBPM;
0100
0101
0102 if all(FigureHandle ~= 0)
0103 if isempty(FigureHandle)
0104 FigureHandle = figure;
0105 clf reset
0106 AxesHandles(1) = subplot(3,1,1);
0107 AxesHandles(2) = subplot(3,1,2);
0108 AxesHandles(3) = subplot(3,1,3);
0109
0110 else
0111 if length(FigureHandle) == 1
0112 FigureHandle = figure(FigureHandle);
0113 clf reset
0114 AxesHandles(1) = subplot(3,1,1);
0115 AxesHandles(2) = subplot(3,1,2);
0116 AxesHandles(3) = subplot(3,1,3);
0117
0118 elseif length(FigureHandle) == 4
0119 FigureHandle = figure;
0120 clf reset
0121 AxesHandles = FigureHandle;
0122 else
0123 error('Improper size of input FigureHandle');
0124 end
0125 end
0126 end
0127
0128 Buffer = .01;
0129 HeightBuffer = .08;
0130 if QMS.QuadPlane == 1
0131 x1 = QMS.x1;
0132 x2 = QMS.x2;
0133
0134
0135 if all(FigureHandle ~= 0)
0136 set(FigureHandle,'units','normal','position',[.0+Buffer .27+Buffer .5-2*Buffer .72-2*Buffer-HeightBuffer]);
0137 end
0138 else
0139 x1 = QMS.y1;
0140 x2 = QMS.y2;
0141
0142
0143 if all(FigureHandle ~= 0)
0144 set(FigureHandle,'units','normal','position',[.5+Buffer .27+Buffer .5-2*Buffer .72-2*Buffer-HeightBuffer]);
0145 end
0146 end
0147
0148
0149 [BPMelem1, iNotFound] = findrowindex(QMS.BPMDev, QMS.BPMDevList);
0150 if ~isempty(iNotFound)
0151 error('BPM at the quadrupole not found in the BPM device list');
0152 end
0153
0154
0155 if length(sigmaBPM) == 1
0156 sigmaBPM = ones(size(x1,1),1) * sigmaBPM;
0157 end
0158
0159 N = size(x1,2);
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251 Gx = getgain('BPMx', QMS.BPMDevList);
0252 Gy = getgain('BPMy', QMS.BPMDevList);
0253 C = getcrunch('BPMx', QMS.BPMDevList);
0254 R = getroll('BPMx', QMS.BPMDevList);
0255
0256 for i = 1:length(Gx)
0257 m = [cos(R(i)) -sin(R(i)); sin(R(i)) cos(R(i))] * [1 C(i); C(i) 1] * [Gx(i) 0;0 Gy(i)] / sqrt(1-C(i)^2);
0258
0259 for j = 1:size(QMS.x1,2)
0260 if j == 1
0261 if isfield(QMS, 'x0')
0262 a = m * [QMS.x0(i,j); QMS.y0(i,j)];
0263 QMS.x0(i,j) = a(1);
0264 QMS.y0(i,j) = a(2);
0265 end
0266 end
0267
0268 a = m * [QMS.x1(i,j); QMS.y1(i,j)];
0269 QMS.x1(i,j) = a(1);
0270 QMS.y1(i,j) = a(2);
0271
0272 a = m * [QMS.x2(i,j); QMS.y2(i,j)];
0273 QMS.x2(i,j) = a(1);
0274 QMS.y2(i,j) = a(2);
0275 end
0276 end
0277
0278 x1 = QMS.y1;
0279 x2 = QMS.y2;
0280
0281
0282
0283 if isfield(QMS, 'OldCenter')
0284
0285 end
0286
0287 if isfield(QMS, 'Orbit0')
0288
0289 BPMUnitsString = QMS.Orbit0.UnitsString;
0290 else
0291 BPMUnitsString = 'm';
0292 end
0293
0294
0295
0296 if strcmpi(QMS.ModulationMethod, 'sweep')
0297
0298
0299 x = (x1(BPMelem1,:)' + x2(BPMelem1,:)')/2;
0300 elseif strcmpi(QMS.ModulationMethod, 'bipolar')
0301
0302 x = (x1(BPMelem1,:)' + x2(BPMelem1,:)')/2;
0303 elseif strcmpi(QMS.ModulationMethod, 'unipolar')
0304
0305
0306 x = (x1(BPMelem1,:)' + x2(BPMelem1,:)')/2;
0307 end
0308
0309
0310
0311 if all(FigureHandle ~= 0)
0312 axes(AxesHandles(1));
0313 plot(x, x2-x1, '-x');
0314
0315 xlabel(sprintf('%s(%d,%d), raw values [%s]', QMS.BPMFamily, QMS.BPMDev(1), QMS.BPMDev(2), BPMUnitsString));
0316 ylabel(sprintf('%s [%s]', QMS.BPMFamily, BPMUnitsString));
0317 if isempty(FileName)
0318 title(sprintf('Center for %s(%d,%d) %s(%d,%d)', QMS.BPMFamily, QMS.BPMDev(1), QMS.BPMDev(2), QMS.QuadFamily, QMS.QuadDev), 'interpreter', 'none');
0319 else
0320 title(sprintf('Center for %s(%d,%d) %s(%d,%d) (%s)', QMS.BPMFamily, QMS.BPMDev(1), QMS.BPMDev(2), QMS.QuadFamily, QMS.QuadDev, FileName), 'interpreter', 'none');
0321 end
0322 grid on
0323 axis tight
0324 end
0325
0326 if isempty(FileName)
0327 fprintf(' Calculating the center of %s(%d,%d) using %s(%d,%d)\n', QMS.QuadFamily, QMS.QuadDev, QMS.BPMFamily, QMS.BPMDev);
0328 else
0329 fprintf(' Calculating the center of %s(%d,%d) using %s(%d,%d) (Data file: %s)\n', QMS.QuadFamily, QMS.QuadDev, QMS.BPMFamily, QMS.BPMDev, FileName);
0330 end
0331 fprintf(' Quadrupole modulation delta = %.3f amps, max. corrector step = %.3f amps\n', QMS.QuadDelta, QMS.CorrDelta);
0332
0333
0334
0335 merit = x2 - x1;
0336 if QuadraticFit
0337 X = [ones(size(x)) x x.^2];
0338 fprintf(' %d point parabolic least squares fit\n', N);
0339 else
0340 X = [ones(size(x)) x];
0341 fprintf(' %d point linear least squares fit\n', N);
0342 end
0343
0344
0345
0346 if all(FigureHandle ~= 0)
0347 axes(AxesHandles(2));
0348 xx = linspace(x(1), x(end), 200);
0349 end
0350
0351 iBPMOutlier = [];
0352 invXX = inv(X'*X);
0353 invXX_X = invXX * X';
0354
0355 for i = 1:size(x1,1)
0356
0357 b = invXX_X * merit(i,:)';
0358 bhat(i,:) = b';
0359
0360
0361
0362
0363
0364
0365 bstd = sigmaBPM(i) * invXX;
0366 bhatstd(i,:) = diag(bstd)';
0367
0368 if all(FigureHandle ~= 0)
0369 if QuadraticFit
0370 y = b(3)*xx.^2 + b(2)*xx + b(1);
0371 else
0372 y = b(2)*xx + b(1);
0373 end
0374
0375 end
0376
0377
0378 if QuadraticFit
0379 y = b(3)*x.^2 + b(2)*x + b(1);
0380 else
0381 y = b(2)*x + b(1);
0382 end
0383 if max(abs(y - merit(i,:)')) > OutlierFactor * sigmaBPM(i)
0384 iBPMOutlier = [iBPMOutlier;i];
0385 end
0386
0387 if QuadraticFit
0388
0389 if b(2) > 0
0390 offset(i,1) = (-b(2) + sqrt(b(2)^2 - 4*b(3)*b(1))) / (2*b(3));
0391 else
0392 offset(i,1) = (-b(2) - sqrt(b(2)^2 - 4*b(3)*b(1))) / (2*b(3));
0393 end
0394 if ~isreal(offset(i,1))
0395
0396
0397 offset(i,1) = -b(2) / b(1) / 2;
0398 end
0399 else
0400
0401 offset(i,1) = -b(1)/b(2);
0402 end
0403 end
0404
0405 QMS.Offset = offset;
0406 QMS.FitParameters = bhat;
0407 QMS.FitParametersStd = bhatstd;
0408 QMS.BPMStd = sigmaBPM;
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421 fprintf(' %d total BPMs\n', length(offset));
0422 fprintf(' BPMs are removed for 1. Bad Status, 2. BPM Outlier, 3. Small Slope, or 4. Center Outlier\n');
0423
0424
0425
0426
0427
0428
0429 iStatus = find(QMS.BPMStatus==0);
0430 iBad = iStatus;
0431 if length(iBad) == length(offset)
0432 error('All the BPMs have bad status');
0433 end
0434 offset1 = offset;
0435 offset1(iBad) = [];
0436 m2 = mean(offset1);
0437 s2 = std(offset1);
0438 fprintf(' 1. Mean = %+.5f %s, STD = %.5f %s, %2d points with bad status\n', m2, BPMUnitsString, s2, BPMUnitsString, length(iBad));
0439
0440
0441 iBad = unique([iStatus; iBPMOutlier]);
0442 if length(iBad) == length(offset)
0443 error('All BPMs either have bad status or failed the BPM outlier condition');
0444 end
0445 offset1 = offset;
0446 offset1(iBad) = [];
0447 m2 = mean(offset1);
0448 s2 = std(offset1);
0449 fprintf(' 2. Mean = %+.5f %s, STD = %.5f %s, %2d points with condition 1 and abs(fit - measured data) > %.2f std(BPM) (BPM outlier)\n', m2, BPMUnitsString, s2, BPMUnitsString, length(iBad), OutlierFactor);
0450
0451
0452
0453
0454
0455
0456 Slopes = abs(bhat(:,2));
0457 [Slopes, i] = sort(Slopes);
0458 Slopes = Slopes(round(end/2):end);
0459 if length(Slopes) > 5
0460 SlopesMax = Slopes(end-4);
0461 else
0462 SlopesMax = Slopes(end);
0463 end
0464
0465
0466
0467 iSlope = find(abs(bhat(:,2)) < SlopesMax * MinSlopeFraction);
0468 iBad = unique([iStatus; iBPMOutlier; iSlope]);
0469 if length(iBad) == length(offset)
0470 error('All BPMs either have bad status, failed the BPM outlier condition, or failed the slope condition');
0471 end
0472 offset1 = offset;
0473 offset1(iBad) = [];
0474 m2 = mean(offset1);
0475 s2 = std(offset1);
0476 fprintf(' 3. Mean = %+.5f %s, STD = %.5f %s, %2d points with condition 1, 2, and slope < %.2f max(slope)\n', m2, BPMUnitsString, s2, BPMUnitsString, length(iBad), MinSlopeFraction);
0477
0478
0479
0480 itotal = (1:length(offset))';
0481 iok = itotal;
0482
0483 offset1 = offset;
0484 offset1(iBad) = [];
0485 iok(iBad) = [];
0486
0487 i = find(abs(offset1-mean(offset1)) > CenterOutlierFactor * std(offset1));
0488 iCenterOutlier = iok(i);
0489 iBad = unique([iBad; iCenterOutlier]);
0490 if length(iBad) == length(offset)
0491 error('All BPMs either have bad status, failed the BPM outlier condition, or failed the slope condition, , or failed the center outlier condition');
0492 end
0493 offset1(i) = [];
0494 iok(i) = [];
0495
0496 m2 = mean(offset1);
0497 s2 = std(offset1);
0498 QMS.GoodIndex = iok;
0499 fprintf(' 4. Mean = %+.5f %s, STD = %.5f %s, %2d points with condition 1, 2, 3, and abs(center-mean(center)) > %.2f std(center) (Center outlier)\n', m2, BPMUnitsString, s2, BPMUnitsString, length(iBad), CenterOutlierFactor);
0500
0501
0502 NN = length(offset);
0503
0504
0505 if all(FigureHandle ~= 0)
0506 axes(AxesHandles(3));
0507 [xx1,yy1]=stairs(1:NN,offset);
0508 offset1 = offset;
0509 offset1(iBad) = NaN*ones(length(iBad),1);
0510 [xx2, yy2] = stairs(1:NN, offset1);
0511 plot(xx1,yy1,'r', xx2,yy2,'b');
0512 xlabel('BPM Number');
0513 ylabel(sprintf('BPM Center [%s]', BPMUnitsString));
0514 grid on
0515 axis tight
0516
0517 axis([0 NN+1 min(offset1)-.1e-6 max(offset1)+.1e-6]);
0518 end
0519
0520
0521
0522
0523 if all(FigureHandle ~= 0)
0524 if 0
0525
0526 axes(AxesHandles(2));
0527 for j = 1:length(iBad)
0528 i = iBad(j);
0529 if QuadraticFit
0530 y = bhat(i,3)*xx.^2 + bhat(i,2)*xx + bhat(i,1);
0531 else
0532 y = bhat(i,2)*xx + bhat(i,1);
0533 end
0534 plot(xx, y,'r');
0535 end
0536 hold off
0537 axis tight
0538 else
0539
0540 axes(AxesHandles(2));
0541 yy = [];
0542 for i = 1:size(x1,1)
0543 if ~any(i == iBad)
0544 if QuadraticFit
0545 y = bhat(i,3)*xx.^2 + bhat(i,2)*xx + bhat(i,1);
0546 else
0547 y = bhat(i,2)*xx + bhat(i,1);
0548 end
0549 yy = [yy;y];
0550 end
0551 end
0552 plot(xx, yy);
0553 hold off
0554 grid on
0555 axis tight
0556 end
0557 xlabel(sprintf('%s(%d,%d), raw values [%s]', QMS.BPMFamily, QMS.BPMDev(1), QMS.BPMDev(2), BPMUnitsString));
0558 ylabel(sprintf('BPM LS Fit [%s]', BPMUnitsString));
0559 grid on
0560 axis tight
0561 end
0562
0563
0564
0565 if ~isempty(iStatus)
0566 if ~isempty(find(iStatus==BPMelem1))
0567 fprintf(' WARNING: BPM(%d,%d) has a bad status\n', QMS.BPMDev(1), QMS.BPMDev(2));
0568 WarningString = sprintf('BPM(%d,%d) has a bad status', QMS.BPMDev(1), QMS.BPMDev(2));
0569 end
0570 end
0571 if ~isempty(iBPMOutlier)
0572 if ~isempty(find(iBPMOutlier==BPMelem1))
0573 fprintf(' WARNING: BPM(%d,%d) removed due to outlier (based on std(BPM))\n', QMS.BPMDev(1), QMS.BPMDev(2));
0574 WarningString = sprintf('BPM(%d,%d) removed due to outlier (based on std(BPM))', QMS.BPMDev(1), QMS.BPMDev(2));
0575 end
0576 end
0577 if ~isempty(iSlope)
0578 if ~isempty(find(iSlope==BPMelem1))
0579 fprintf(' WARNING: BPM(%d,%d) slope is too small\n', QMS.BPMDev(1), QMS.BPMDev(2));
0580 WarningString = sprintf('BPM(%d,%d) slope is too small', QMS.BPMDev(1), QMS.BPMDev(2));
0581 end
0582 end
0583 if ~isempty(iCenterOutlier)
0584 if ~isempty(find(iCenterOutlier==BPMelem1))
0585 fprintf(' WARNING: BPM(%d,%d) removed due to outlier (based on all the centers)\n', QMS.BPMDev(1), QMS.BPMDev(2));
0586 WarningString = sprintf('BPM(%d,%d) ', QMS.BPMDev(1), QMS.BPMDev(2));
0587 end
0588 end
0589
0590
0591
0592
0593
0594
0595
0596
0597
0598
0599
0600
0601
0602
0603
0604
0605
0606
0607
0608
0609
0610
0611
0612
0613
0614
0615
0616
0617
0618
0619
0620
0621
0622
0623
0624
0625
0626
0627 if ~isempty(QMS.OldCenter)
0628 fprintf(' Starting Offset %s(%d,%d) = %+f [%s]\n', QMS.BPMFamily, QMS.BPMDev, QMS.OldCenter, BPMUnitsString);
0629 end
0630 fprintf(' New Offset %s(%d,%d) = %+f [%s]\n', QMS.BPMFamily, QMS.BPMDev, m2, BPMUnitsString);
0631
0632 QMS.Center = m2;
0633 QMS.CenterSTD = s2;
0634
0635
0636 if all(FigureHandle ~= 0)
0637 addlabel(1, 0, datestr(QMS.TimeStamp));
0638 addlabel(0, 0, sprintf('Offset %s(%d,%d)=%f, {\\Delta}%s(%d,%d)=%f, {\\Delta}%s(%d,%d)=%f', QMS.BPMFamily, QMS.BPMDev, QMS.Center, QMS.QuadFamily, QMS.QuadDev, QMS.QuadDelta, QMS.CorrFamily, QMS.CorrDevList(1,:), QMS.CorrDelta(1)));
0639 end
0640
0641 fprintf('\n');
0642
0643
0644
0645 if all(FigureHandle ~= 0)
0646 QMS = quaderrors(QMS, gcf+1);
0647 else
0648
0649 QMS = quaderrors(QMS, 0);
0650 end
0651
0652
0653