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 = 'mm';
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
0314 plot(x, x2-x1, '-x');
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
0318
0319
0320 if isempty(FileName)
0321 title(sprintf('Center for %s(%d,%d) %s(%d,%d)', QMS.BPMFamily, QMS.BPMDev(1), QMS.BPMDev(2), QMS.QuadFamily, QMS.QuadDev), 'interpreter', 'none');
0322 else
0323 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');
0324 end
0325 grid on
0326 axis tight
0327 end
0328
0329 if isempty(FileName)
0330 fprintf(' Calculating the center of %s(%d,%d) using %s(%d,%d)\n', QMS.QuadFamily, QMS.QuadDev, QMS.BPMFamily, QMS.BPMDev);
0331 else
0332 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);
0333 end
0334 fprintf(' Quadrupole modulation delta = %.3f amps, max. corrector step = %.3f amps\n', QMS.QuadDelta, QMS.CorrDelta);
0335
0336
0337
0338 merit = x2 - x1;
0339 if QuadraticFit
0340 X = [ones(size(x)) x x.^2];
0341 fprintf(' %d point parabolic least squares fit\n', N);
0342 else
0343 X = [ones(size(x)) x];
0344 fprintf(' %d point linear least squares fit\n', N);
0345 end
0346
0347
0348
0349 if all(FigureHandle ~= 0)
0350 axes(AxesHandles(2));
0351 xx = linspace(x(1), x(end), 200);
0352 end
0353
0354 iBPMOutlier = [];
0355 invXX = inv(X'*X);
0356 invXX_X = invXX * X';
0357
0358 for i = 1:size(x1,1)
0359
0360 b = invXX_X * merit(i,:)';
0361 bhat(i,:) = b';
0362
0363
0364
0365
0366
0367
0368 bstd = sigmaBPM(i) * invXX;
0369 bhatstd(i,:) = diag(bstd)';
0370
0371 if all(FigureHandle ~= 0)
0372 if QuadraticFit
0373 y = b(3)*xx.^2 + b(2)*xx + b(1);
0374 else
0375 y = b(2)*xx + b(1);
0376 end
0377
0378 end
0379
0380
0381 if QuadraticFit
0382 y = b(3)*x.^2 + b(2)*x + b(1);
0383 else
0384 y = b(2)*x + b(1);
0385 end
0386 if max(abs(y - merit(i,:)')) > OutlierFactor * sigmaBPM(i)
0387 iBPMOutlier = [iBPMOutlier;i];
0388 end
0389
0390 if QuadraticFit
0391
0392 if b(2) > 0
0393 offset(i,1) = (-b(2) + sqrt(b(2)^2 - 4*b(3)*b(1))) / (2*b(3));
0394 else
0395 offset(i,1) = (-b(2) - sqrt(b(2)^2 - 4*b(3)*b(1))) / (2*b(3));
0396 end
0397 if ~isreal(offset(i,1))
0398
0399
0400 offset(i,1) = -b(2) / b(1) / 2;
0401 end
0402 else
0403
0404 offset(i,1) = -b(1)/b(2);
0405 end
0406 end
0407
0408 QMS.Offset = offset;
0409 QMS.FitParameters = bhat;
0410 QMS.FitParametersStd = bhatstd;
0411 QMS.BPMStd = sigmaBPM;
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423
0424 fprintf(' %d total BPMs\n', length(offset));
0425 fprintf(' BPMs are removed for 1. Bad Status, 2. BPM Outlier, 3. Small Slope, or 4. Center Outlier\n');
0426
0427
0428
0429
0430
0431
0432 iStatus = find(QMS.BPMStatus==0);
0433 iBad = iStatus;
0434 if length(iBad) == length(offset)
0435 error('All the BPMs have bad status');
0436 end
0437 offset1 = offset;
0438 offset1(iBad) = [];
0439 m2 = mean(offset1);
0440 s2 = std(offset1);
0441 fprintf(' 1. Mean = %+.5f %s, STD = %.5f %s, %2d points with bad status\n', m2, BPMUnitsString, s2, BPMUnitsString, length(iBad));
0442
0443
0444 iBad = unique([iStatus; iBPMOutlier]);
0445 if length(iBad) == length(offset)
0446 error('All BPMs either have bad status or failed the BPM outlier condition');
0447 end
0448 offset1 = offset;
0449 offset1(iBad) = [];
0450 m2 = mean(offset1);
0451 s2 = std(offset1);
0452 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);
0453
0454
0455
0456
0457
0458
0459 Slopes = abs(bhat(:,2));
0460 [Slopes, i] = sort(Slopes);
0461 Slopes = Slopes(round(end/2):end);
0462 if length(Slopes) > 5
0463 SlopesMax = Slopes(end-4);
0464 else
0465 SlopesMax = Slopes(end);
0466 end
0467
0468
0469
0470 iSlope = find(abs(bhat(:,2)) < SlopesMax * MinSlopeFraction);
0471 iBad = unique([iStatus; iBPMOutlier; iSlope]);
0472 if length(iBad) == length(offset)
0473 error('All BPMs either have bad status, failed the BPM outlier condition, or failed the slope condition');
0474 end
0475 offset1 = offset;
0476 offset1(iBad) = [];
0477 m2 = mean(offset1);
0478 s2 = std(offset1);
0479 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);
0480
0481
0482
0483 itotal = (1:length(offset))';
0484 iok = itotal;
0485
0486 offset1 = offset;
0487 offset1(iBad) = [];
0488 iok(iBad) = [];
0489
0490 i = find(abs(offset1-mean(offset1)) > CenterOutlierFactor * std(offset1));
0491 iCenterOutlier = iok(i);
0492 iBad = unique([iBad; iCenterOutlier]);
0493 if length(iBad) == length(offset)
0494 error('All BPMs either have bad status, failed the BPM outlier condition, or failed the slope condition, , or failed the center outlier condition');
0495 end
0496 offset1(i) = [];
0497 iok(i) = [];
0498
0499 m2 = mean(offset1);
0500 s2 = std(offset1);
0501 QMS.GoodIndex = iok;
0502 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);
0503
0504
0505 NN = length(offset);
0506
0507
0508 if all(FigureHandle ~= 0)
0509 axes(AxesHandles(3));
0510 [xx1,yy1]=stairs(1:NN,offset);
0511 offset1 = offset;
0512 offset1(iBad) = NaN*ones(length(iBad),1);
0513 [xx2, yy2] = stairs(1:NN, offset1);
0514 plot(xx1,yy1,'r', xx2,yy2,'b');
0515 ylabel(sprintf('BPM Center [%s]', BPMUnitsString));
0516
0517
0518 xlabel('BPM Number');
0519 grid on
0520 axis tight
0521
0522
0523
0524 axis([1 NN+1 min(offset1)-.1 max(offset1)+.1]);
0525 end
0526
0527
0528
0529
0530 if all(FigureHandle ~= 0)
0531 if 0
0532
0533 axes(AxesHandles(2));
0534 for j = 1:length(iBad)
0535 i = iBad(j);
0536 if QuadraticFit
0537 y = bhat(i,3)*xx.^2 + bhat(i,2)*xx + bhat(i,1);
0538 else
0539 y = bhat(i,2)*xx + bhat(i,1);
0540 end
0541 plot(xx, y,'r');
0542 end
0543 hold off
0544 axis tight
0545 else
0546
0547 axes(AxesHandles(2));
0548 yy = [];
0549 for i = 1:size(x1,1)
0550 if ~any(i == iBad)
0551 if QuadraticFit
0552 y = bhat(i,3)*xx.^2 + bhat(i,2)*xx + bhat(i,1);
0553 else
0554 y = bhat(i,2)*xx + bhat(i,1);
0555 end
0556 yy = [yy;y];
0557 end
0558 end
0559
0560 plot(1000*xx, 1000*yy);
0561 hold off
0562 grid on
0563 axis tight
0564 end
0565 xlabel(sprintf('%s(%d,%d), raw values [%s]', QMS.BPMFamily, QMS.BPMDev(1), QMS.BPMDev(2), BPMUnitsString));
0566 ylabel(sprintf('BPM LS Fit [%s]', BPMUnitsString));
0567
0568
0569 grid on
0570 axis tight
0571 end
0572
0573
0574
0575 if ~isempty(iStatus)
0576 if ~isempty(find(iStatus==BPMelem1))
0577 fprintf(' WARNING: BPM(%d,%d) has a bad status\n', QMS.BPMDev(1), QMS.BPMDev(2));
0578 WarningString = sprintf('BPM(%d,%d) has a bad status', QMS.BPMDev(1), QMS.BPMDev(2));
0579 end
0580 end
0581 if ~isempty(iBPMOutlier)
0582 if ~isempty(find(iBPMOutlier==BPMelem1))
0583 fprintf(' WARNING: BPM(%d,%d) removed due to outlier (based on std(BPM))\n', QMS.BPMDev(1), QMS.BPMDev(2));
0584 WarningString = sprintf('BPM(%d,%d) removed due to outlier (based on std(BPM))', QMS.BPMDev(1), QMS.BPMDev(2));
0585 end
0586 end
0587 if ~isempty(iSlope)
0588 if ~isempty(find(iSlope==BPMelem1))
0589 fprintf(' WARNING: BPM(%d,%d) slope is too small\n', QMS.BPMDev(1), QMS.BPMDev(2));
0590 WarningString = sprintf('BPM(%d,%d) slope is too small', QMS.BPMDev(1), QMS.BPMDev(2));
0591 end
0592 end
0593 if ~isempty(iCenterOutlier)
0594 if ~isempty(find(iCenterOutlier==BPMelem1))
0595 fprintf(' WARNING: BPM(%d,%d) removed due to outlier (based on all the centers)\n', QMS.BPMDev(1), QMS.BPMDev(2));
0596 WarningString = sprintf('BPM(%d,%d) ', QMS.BPMDev(1), QMS.BPMDev(2));
0597 end
0598 end
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
0628
0629
0630
0631
0632
0633
0634
0635
0636
0637 if ~isempty(QMS.OldCenter)
0638 fprintf(' Starting Offset %s(%d,%d) = %+f [%s]\n', QMS.BPMFamily, QMS.BPMDev, QMS.OldCenter, BPMUnitsString);
0639 end
0640 fprintf(' New Offset %s(%d,%d) = %+f [%s]\n', QMS.BPMFamily, QMS.BPMDev, m2, BPMUnitsString);
0641
0642 QMS.Center = m2;
0643 QMS.CenterSTD = s2;
0644
0645
0646 if all(FigureHandle ~= 0)
0647 addlabel(1, 0, datestr(QMS.TimeStamp));
0648 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)));
0649 end
0650
0651 fprintf('\n');
0652
0653
0654
0655 if all(FigureHandle ~= 0)
0656 QMS = quaderrors(QMS, gcf+1);
0657 else
0658
0659 QMS = quaderrors(QMS, 0);
0660 end
0661
0662
0663