StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
calibFmsTools.C
1 /*
2  FMS calibration tools
3 
4  Chong Kim
5  UC Riverside
6  ckim@bnl.gov
7 
8  * Functions are sorted in alphabetical order unless dependency problem exist
9 */
10 
11 #include "TBox.h"
12 #include "TCanvas.h"
13 #include "TDatime.h"
14 #include "TEllipse.h"
15 #include "TF1.h"
16 #include "TFile.h"
17 #include "TGaxis.h"
18 #include "TGraph.h"
19 #include "TGraphErrors.h"
20 #include "TH1.h"
21 #include "TH2.h"
22 #include "TKey.h"
23 #include "TMath.h"
24 #include "TLeaf.h"
25 #include "TLegend.h"
26 #include "TLine.h"
27 #include "TMarker.h"
28 #include "TPaveText.h"
29 #include "TRandom2.h"
30 #include "TStopwatch.h"
31 #include "TString.h"
32 #include "TSystem.h"
33 #include "TStyle.h"
34 #include "TTree.h"
35 
36 #include <cmath>
37 #include <fstream>
38 #include <iostream>
39 #include <map>
40 using namespace std;
41 
42 //----------------
43 enum CellStatIndex
44 {
45  GOOD = 0,
46  BAD = 1,
47  DEAD = 2,
48  CONVERGED = 9
49 };
50 
51 //----------------------------
52 typedef struct //Cell position
53 {
54  int col;
55  int row;
56  float chX;
57  float chY;
58 } st_pos;
59 
60 //--------------------------
61 typedef struct //Fit results
62 {
63  int nRefit;
64  float chi2;
65  float mass;
66  float massErr;
67  float width;
68  float widthErr;
69 } st_fitR;
70 
71 //---------------------------------
72 double F1Gaus(double* x, double* p)
73 {
74  double X = x[0];
75  double Height = p[0];
76  double Center = p[1];
77  double Width = p[2];
78  double Return = Height * TMath::Gaus(X, Center, Width);
79  return Return;
80 }//F1Gaus
81 
82 //---------------------------------
83 double F1Pol3(double* x, double* p)
84 {
85  double X = x[0];
86  double Return = (X - p[0]) * (p[1] + p[2]*X + p[3]*std::pow(X, 2));
87  return Return;
88 }//F1Pol3
89 
90 //---------------------------------
91 double F1Comb(double* x, double* p)
92 {
93  return F1Gaus(x, p) + F1Pol3(x, &p[3]);
94 }//F1Comb
95 
96 //--------------------------------------------------------------------------------
97 void GetMapChToBS(const char* inList, map<int, int> chToBS[4], bool PRINT = false)
98 {
99  //Uses file FmsBitShift.txt
100 
101  ifstream in;
102  in.open(inList);
103  if (!in.is_open()) { cout <<"Cannot open " <<inList <<endl; return; }
104  while (in.is_open())
105  {
106  int detId, ch, bs;
107  in >> detId >> ch >> bs;
108  if (!in.good()) { break; in.close(); }
109 
110  chToBS[detId-8].insert(pair<int, int>(ch, bs));
111  if (PRINT) cout <<Form("%2i %3i %2i", detId, ch, bs) <<endl;
112  }
113 
114  return;
115 }//GetMapChToBS
116 
117 //--------------------------------------------------------------------------------------------
118 void GetMapChToCellStat(const char* inList, map<int, int> chToCellStat[4], bool PRINT = false)
119 {
120  //Uses file FmsCellStat.txt
121 
122  ifstream in;
123  in.open(inList);
124  if (!in.is_open()) { cout <<"Cannot open " <<inList <<endl; return; }
125  while (in.is_open())
126  {
127  int detId, ch, stat;
128  in >> detId >> ch >> stat;
129  if (!in.good()) { break; in.close(); }
130 
131  chToCellStat[detId-8].insert(pair<int, int>(ch, stat));
132  if (PRINT) cout <<Form("%2i %3i %i", detId, ch, stat) <<endl;
133  }
134 
135  return;
136 }//GetMapChToCellStat
137 
138 //----------------------------------------------------------------------------------------
139 void GetMapChToFitR(const char* inList, map<int, st_fitR> chToFitR[4], bool PRINT = false)
140 {
141  //Uses file out_fmsCalibFit_?.txt, which is produced by FitMass
142 
143  ifstream in;
144  in.open(inList);
145  if (!in.is_open()) { cout <<"Cannot open " <<inList <<endl; return; }
146  while (in.is_open())
147  {
148  int detId, ch, nRefit;
149  float chi2, mass, massErr, width, widthErr;
150  in >> detId >> ch >> nRefit >> chi2 >> mass >> massErr >> width >> widthErr;
151  if (!in.good()) { break; in.close(); }
152 
153  st_fitR fitR;
154  fitR.nRefit = nRefit;
155  fitR.chi2 = chi2;
156  fitR.mass = mass;
157  fitR.massErr = massErr;
158  fitR.width = width;
159  fitR.widthErr = widthErr;
160  chToFitR[detId-8].insert(pair<int, st_fitR>(ch, fitR));
161  if (PRINT)
162  {
163  cout <<Form("%2i %3i %2i %7.3f %6.3f %6.3f %6.3f %6.3f",
164  detId,ch,nRefit,chi2,mass,massErr,width,widthErr) <<endl;
165  }
166  }
167 
168  return;
169 }//GetMapChToFitR
170 
171 //--------------------------------------------------------------------------------------
172 void GetMapChToGain(const char* inList, map<int, float> chToGain[4], bool PRINT = false)
173 {
174  //Uses file FmsMapBase.txt, NOTE that this is gain, NOT gainCorr!
175 
176  ifstream in;
177  in.open(inList);
178  if (!in.is_open()) { cout <<"Cannot open " <<inList <<endl; return; }
179  while (in.is_open())
180  {
181  int detId, ch, col, row;
182  float gain, chX, chY;
183  in >> detId >> ch >> gain >> col >> row >> chX >> chY;
184  if (!in.good()) { break; in.close(); }
185 
186  if (gain == 0.) continue; //NOT necessary after update in Feb. 2019, but leaving it as a fafeguard
187  else
188  {
189  int a = detId-8;
190  chToGain[a].insert(pair<int, float>(ch, gain));
191  if (PRINT) cout <<Form("%2i %3i %5.3f", a+8, ch, gain) <<endl;
192  }
193  }
194 
195  return;
196 }//GetMapChToGain
197 
198 //----------------------------------------------------------------------------------------------
199 void GetMapChToGainCorr(const char* inList, map<int, float> chToGainCorr[4], bool PRINT = false)
200 {
201  //Uses file FmsGainCorr.txt (FmsDbMaker readable)
202 
203  ifstream in;
204  in.open(inList);
205  if (!in.is_open()) { cout <<"Cannot open " <<inList <<endl; return; }
206  while (in.is_open())
207  {
208  int index, nstb, ch;
209  float gainCorr;
210  in >> index >> nstb >> ch >> gainCorr;
211  if (!in.good()) { break; in.close(); }
212 
213  if (index == 1) continue; //PSU group's NSTB notation related, ignore it
214  else
215  {
216  int a = nstb-1;
217  chToGainCorr[a].insert(pair<int, float>(ch, gainCorr));
218  if (PRINT) cout <<Form("%2i %3i %5.3f", a+8, ch, gainCorr) <<endl;
219  }
220  }
221 
222  return;
223 }//GetMapChToGainCorr
224 
225 //-------------------------------------------------------------------------------------
226 void GetMapChToPos(const char* inList, map<int, st_pos> chToPos[4], bool PRINT = false)
227 {
228  //Uses file FmsMapBase.txt
229 
230  ifstream in;
231  in.open(inList);
232  if (!in.is_open()) { cout <<"Cannot open " <<inList <<endl; return; }
233  while (in.is_open())
234  {
235  int detId, ch, col, row;
236  float gain, chX, chY;
237  in >> detId >> ch >> gain >> col >> row >> chX >> chY;
238  if (!in.good()) { break; in.close(); }
239 
240  if (gain == 0.) continue;
241  else
242  {
243  int a = detId-8;
244  st_pos pos;
245  pos.col = col;
246  pos.row = row;
247  pos.chX = chX;
248  pos.chY = chY;
249  chToPos[a].insert(pair<int, st_pos>(ch, pos));
250  if (PRINT) cout <<Form("%2i %3i %2i %2i %6.2f %6.2f", detId, ch, col, row, chX, chY) <<endl;
251  }
252  }
253 
254  return;
255 }//GetMapChToPos
256 
257 //------------------------------------------------------------------------------------
258 void GetMapChToSkew(const char* inList, map<int, int> chToSkew[4], bool PRINT = false)
259 {
260  //Read count for skewed channel monitor (how many times a channel judged as skewed)
261 
262  ifstream in;
263  in.open(inList);
264  if (!in.is_open()) { cout <<"Cannot open " <<inList <<endl; return; }
265  while (in.is_open())
266  {
267  int detId, ch, nSkew;
268  in >> detId >> ch >> nSkew;
269  if (!in.good()) { break; in.close(); }
270 
271  chToSkew[detId-8].insert(pair<int, int>(ch, nSkew));
272  if (PRINT) cout <<Form("%2i %3i %i", detId, ch, nSkew) <<endl;
273  }
274 
275  return;
276 }//GetMapChToSkew
277 
278 //----------------------------------------------------------------------------------
279 void GetMapIndexToCh(const char* inList, map<int, int> iToCh[4], bool PRINT = false)
280 {
281  //Uses file FmsMapBase.txt
282 
283  int index[4] = {0}; //Note that index begins from 0, while channel # begins from 1
284 
285  ifstream in;
286  in.open(inList);
287  if (!in.is_open()) { cout <<"Cannot open " <<inList <<endl; return; }
288  while (in.is_open())
289  {
290  int detId, ch, col, row;
291  float gain, chX, chY;
292  in >> detId >> ch >> gain >> col >> row >> chX >> chY;
293  if (!in.good()) { break; in.close(); }
294 
295  if (gain==0.) continue;
296  else
297  {
298  int a = detId-8;
299  iToCh[a].insert(pair<int, int>(index[a], ch));
300  if (PRINT) cout <<Form("%2i %3i %3i", detId, ch, index[a]) <<endl;
301  index[a]++;
302  }
303  }
304 
305  return;
306 }//GetMapBase
307 
308 //---------------------------------------------------------------------------
309 void GetMapManualGainCorr(const char* inList, map<int, float> manGainCorr[4])
310 {
311  ifstream in;
312  in.open(inList);
313  if (!in.is_open())
314  {
315  cout <<Form("\nNo manual gainCorr update list found: skip manual correction...\n") <<endl;
316  return;
317  }
318 
319  cout <<"\nManual gainCorr update list found: enforce following values for next iteration..." <<endl;
320  while (in.is_open())
321  {
322  int detId, ch;
323  float gainCorr;
324  in >> detId >> ch >> gainCorr;
325  if (!in.good()) { break; in.close(); }
326 
327  cout <<Form("%2i, %3i: %4.3f", detId, ch, gainCorr) <<endl;
328  manGainCorr[detId-8].insert(pair<int, float>(ch, gainCorr));
329  }
330  cout <<endl;
331 
332  return;
333 }//Intervent
334 
335 //---------------------------------------------------------
336 void SetPi0Range(TH1F* H1, float* pi0R, bool PRINT = false)
337 {
338  //Empirically, 1 sigma width of a good cell is 0.02 (large) and 0.03 (small)
339  const float min = 0.135 - 0.06;
340  const float max = 0.135 + 0.06;
341 
342  //Default peak range: [0.10, 0.25]
343  const float tempPeak = H1->GetBinCenter(H1->GetMaximumBin());
344  if (tempPeak >= min && tempPeak <= max)
345  {
346  pi0R[0] = min;
347  pi0R[1] = max;
348  }
349  else
350  {
351  if (tempPeak < min) pi0R[0] = 0.;
352  if (tempPeak > max) pi0R[1] = 0.35;
353  if (PRINT) cout <<Form("Rearranging pi0 range of %s to [%4.3f, %4.3f]\n", H1->GetName(),pi0R[0],pi0R[1]);
354  }
355 
356  return;
357 }//SetPi0Range
358 
359 //---------------------------------------------
360 float SearchFirstNonzeroBinPosition(TH1F* H1BG)
361 {
362  float BGStart = 0.;
363  for (int a=0; a<H1BG->GetNbinsX(); a++)
364  {
365  int BinC = H1BG->GetBinContent(a+1);
366  if (BinC != 0)
367  {
368  BGStart = H1BG->GetBinCenter(a+1);
369  break;
370  }
371  }
372  if (BGStart < 0.01 || BGStart > 0.10) BGStart = 0.05;
373 
374  return BGStart;
375 }//SearchFirstNonzeroBinPosition
376 
377 //-----------
378 void FitMass(
379  const int iIter,
380  TH2F* H2_mass,
381  map<int, int>iToCh,
382  map<int, int>chToBS,
383  map<int, int>chToCellStat,
384  map<int, float>chToGainCorr,
385  map<int, st_pos>chToPos,
386  map<int, st_fitR>&chToFitR,
387  bool PRINT = true
388  )
389 {
390  const int nEventsMin = 100;
391  const int nRefitMax = 10;
392  const float maxMass = 0.5;
393 
394  //Plot container to save it later
395  TCanvas* c1;
396  TLine* LPi0;
397  if (PRINT)
398  {
399  gStyle->SetOptDate(0);
400  gStyle->SetOptStat("e");
401  gStyle->SetOptFit();
402  c1 = new TCanvas("c1", "", 800, 800);
403 
404  LPi0 = new TLine(0.135, 0, 0.135, 1);
405  LPi0->SetLineColor(kMagenta);
406  LPi0->SetLineStyle(2);
407  }
408 
409  //Prepare fit functions
410  TF1* F1Pi0 = new TF1("F1Pi0", F1Gaus, 0, maxMass, 3);
411  TF1* F1BG = new TF1("F1BG", F1Pol3, 0, maxMass, 4);
412  TF1* F1 = new TF1("F1", F1Comb, 0, maxMass, 7);
413  F1Pi0->SetLineColor(4);
414  F1Pi0->SetLineStyle(2);
415  F1Pi0->SetParNames("GausH", "GausM", "GausW");
416  F1BG->SetLineColor(3);
417  F1BG->SetLineStyle(2);
418  F1BG->SetParNames("Pol3p0", "Pol3p1", "Pol3p2", "Pol3p3");
419  F1->SetLineColor(2);
420  F1->SetLineStyle(2);
421  F1->SetParNames("GausH", "GausM", "GausW", "Pol3p0", "Pol3p1", "Pol3p2", "Pol3p3");
422 
423  //Histogram container
424  TH1F* H1Pi0 = new TH1F();
425  TH1F* H1BG = new TH1F();
426  TH1F* H1 = new TH1F();
427 
428  //Loop over channels
429  for (unsigned int b=0; b<iToCh.size(); b++)
430  {
431  H1Pi0->Reset();
432  H1BG ->Reset();
433  H1 ->Reset();
434 
435  //Get info
436  const int ch = iToCh[b];
437  const int tBS = chToBS[ch];
438  const int tCol = chToPos[ch].col;
439  const int tRow = chToPos[ch].row;
440  const float tGainCorr = chToGainCorr[ch];
441  const char* titleInfo = Form("%5.3f, [%i, %i], BS=%i", tGainCorr, tCol, tRow, tBS);
442 
443  //Get mass distribution
444  H1 = (TH1F*)H2_mass->ProjectionY(Form("%s_ch%i", H2_mass->GetName(), ch), ch, ch);
445  if (H1->GetXaxis()->GetXmax() != maxMass) cout <<"WARNING: max X exceeds prepared fit range!" <<endl;
446 
447  //Skip bad, dead, or too small # of entries
448  if (chToCellStat[ch]==BAD || chToCellStat[ch]==DEAD || H1->GetEntries()<nEventsMin)
449  {
450  if (PRINT)
451  {
452  c1->cd(1);
453  c1->SetName(Form("%s", H1->GetName()));
454 
455  const char* titleStat = "";
456  if (chToCellStat[ch] == BAD) titleStat = "BAD";
457  else if (chToCellStat[ch] == DEAD) titleStat = "DEAD";
458  else if (H1->GetEntries() < nEventsMin) titleStat = Form("<%i", nEventsMin);
459  H1->SetTitle(Form("i=%i, %s, %s", iIter, titleInfo, titleStat));
460  H1->DrawCopy("hist e");
461 
462  c1->SetTitle(Form("Skip, %s", titleStat));
463  c1->Write();
464  }
465  continue;
466  }
467 
468  //---------------------------------------
469 
470  //Check if "this distribution's peak" is located near the pi0 mass, update otherwise
471  float pi0R[2] = {0.135-0.06, 0.135+0.06};
472  SetPi0Range(H1, pi0R, true);
473 
474  //Separate mass distribution into two: pi0 and BG
475  const int mMaxB = H1->GetXaxis()->FindBin(maxMass);
476  const float pi0B0 = H1->GetXaxis()->FindBin(pi0R[0]);
477  const float pi0B1 = H1->GetXaxis()->FindBin(pi0R[1]);
478  H1Pi0 = (TH1F*)H1->Clone(Form("%s_pi0", H1->GetName()));
479  H1BG = (TH1F*)H1->Clone(Form("%s_bg", H1->GetName()));
480  for (int c=0; c<mMaxB; c++)
481  {
482  (c+1>=pi0B0 && c+1<=pi0B1)?H1BG->SetBinContent(c+1, 0):H1Pi0->SetBinContent(c+1, 0);
483  (c+1>=pi0B0 && c+1<=pi0B1)?H1BG->SetBinError (c+1, 0):H1Pi0->SetBinError (c+1, 0);
484  }
485 
486  //---------------------------------------
487 
488  //Preliminary fit on pi0 histogram to get proper seed parameters
489  for (int i=0; i<F1Pi0->GetNpar(); i++) F1Pi0->ReleaseParameter(i);
490  const float pi0H = H1Pi0->GetMaximum();
491  const float pi0C = H1Pi0->GetBinCenter(H1Pi0->GetMaximumBin());
492  const float pi0W = 0.03;
493  const float pi0HL[2] = {pi0H*0.1, pi0H};
494  const float pi0CL[2] = {(pi0C<0.1)?0:(pi0C-0.05), pi0C+0.05};
495  const float pi0WL[2] = {H1Pi0->GetBinWidth(1), 0.15};
496  F1Pi0->SetParameters(pi0H*0.9, pi0C, pi0W);
497  F1Pi0->SetParLimits(0, pi0HL[0], pi0HL[1]);
498  F1Pi0->SetParLimits(1, pi0CL[0], pi0CL[1]);
499  F1Pi0->SetParLimits(2, pi0WL[0], pi0WL[1]);
500  H1Pi0->Fit(F1Pi0->GetName(), "EQR0", "", pi0R[0], pi0R[1]);
501  const float GausH = F1Pi0->GetParameter(0);
502  const float GausC = F1Pi0->GetParameter(1);
503  const float GausW = F1Pi0->GetParameter(2);
504 
505  //Preliminary fit on BG
506  for (int i=0; i<F1BG->GetNpar(); i++) F1BG->ReleaseParameter(i);
507  const float Pol3p0 = SearchFirstNonzeroBinPosition(H1BG);
508  F1BG->SetParameters(1, 1, 1, 1);
509  F1BG->FixParameter(0, Pol3p0);
510  H1BG->Fit(F1BG->GetName(), "EQR0", "", 0, maxMass);
511  const float Pol3p1 = F1BG->GetParameter(1);
512  const float Pol3p2 = F1BG->GetParameter(2);
513  const float Pol3p3 = F1BG->GetParameter(3);
514 
515  //Combined fit
516  for (int i=0; i<F1->GetNpar(); i++) F1->ReleaseParameter(i);
517  F1->SetParameters(GausH, GausC, GausW, Pol3p0, Pol3p1, Pol3p2, Pol3p3);
518  F1->SetParLimits(0, pi0HL[0], pi0HL[1]);
519  F1->SetParLimits(1, pi0CL[0], pi0CL[1]);
520  F1->SetParLimits(2, pi0WL[0], pi0WL[1]);
521  F1->FixParameter(3, Pol3p0);
522  H1->Fit(F1->GetName(), "EQR0", "", 0, maxMass);
523 
524  //---------------------------------------
525 
526  //Try fit again if fit qaulity looks too bad
527  int nRefit = 0;
528  float massDev = fabs(F1->GetParameter(1) - 0.1349766);
529  float fitChi2 = F1->GetChisquare()/F1->GetNDF();
530  if (massDev>0.03 && (fitChi2<0.5 || fitChi2>3.0))
531  {
532  while (nRefit < nRefitMax)
533  {
534  nRefit++;
535  if (massDev<0.03 && fitChi2>0.5 && fitChi2<3.0) break;
536  //cout <<Form("Try fit again... %s, %2i/%i", H1->GetName(), nRefit, nRefitMax) <<endl;
537 
538  TDatime DT;
539  TRandom2 RNDM(DT.GetTime() + nRefit);
540  const float pNew[7] =
541  {
542  RNDM.Uniform(H1->GetMaximum()*0.5, H1->GetMaximum()),
543  RNDM.Gaus(0.135, 0.05),
544  RNDM.Uniform(H1->GetBinWidth(1), 0.3),
545  Pol3p0, 1., 1., 1.
546  }; //Set Gaussian part's parameters again
547 
548  for (int i=0; i<F1->GetNpar(); i++) { F1->ReleaseParameter(i); F1->SetParameter(i, pNew[i]); }
549  F1->SetParLimits(0, H1->GetMaximum()*0.5, H1->GetMaximum());
550  F1->SetParLimits(1, 0, maxMass);
551  F1->SetParLimits(2, H1->GetBinWidth(1), 0.3);
552  F1->FixParameter(3, Pol3p0);
553 
554  H1->Fit(F1->GetName(), "EQR0", "", 0, maxMass);
555  massDev = fabs(F1->GetParameter(1) - 0.1349766);
556  fitChi2 = F1->GetChisquare()/F1->GetNDF();
557  }
558  }//reFit
559 
560  //---------------------------------------
561 
562  //Save results
563  st_fitR fitR;
564  fitR.nRefit = nRefit;
565  fitR.chi2 = fitChi2;
566  fitR.mass = F1->GetParameter(1);
567  fitR.massErr = F1->GetParError(1);
568  fitR.width = F1->GetParameter(2);
569  fitR.widthErr = F1->GetParError(2);
570  chToFitR.insert(pair<int, st_fitR>(ch, fitR));
571 
572  if (PRINT)
573  {
574  c1->cd(1);
575  c1->SetName(Form("%s", H1->GetName()));
576 
577  const char* titleStat = "";
578  if (chToCellStat[ch] == GOOD) titleStat = "";
579  else if (chToCellStat[ch] == CONVERGED) titleStat = ", CONV";
580  const char* titleRefit = (nRefit!=0)?Form(", nRefit=%i", nRefit):"";
581  H1->SetTitle(Form("i=%i, %s%s%s", iIter, titleInfo, titleStat, titleRefit));
582  H1->DrawCopy("hist e");
583 
584  F1Pi0->SetParameter(0, F1->GetParameter(0));
585  F1Pi0->SetParameter(1, F1->GetParameter(1));
586  F1Pi0->SetParameter(2, F1->GetParameter(2));
587  F1Pi0->Draw("same");
588  F1BG->SetParameter(0, F1->GetParameter(3));
589  F1BG->SetParameter(1, F1->GetParameter(4));
590  F1BG->SetParameter(2, F1->GetParameter(5));
591  F1BG->SetParameter(3, F1->GetParameter(6));
592  F1BG->Draw("same");
593  F1->Draw("same");
594 
595  LPi0->SetY2(H1->GetMaximum());
596  LPi0->Draw("same");
597 
598  c1->SetTitle(titleRefit);
599  c1->Write();
600  }//Print
601 
602  }//b, channels
603 
604  H1Pi0->Delete();
605  H1BG ->Delete();
606  H1 ->Delete();
607  F1Pi0->Delete();
608  F1BG ->Delete();
609  F1 ->Delete();
610 
611  return;
612 }//FitMass
613 
614 //-------------------------------------------------------------------------------------------
615 void PrintCellStat(const char* outName, map<int, int>iToCh[4], map<int, int> chToCellStat[4])
616 {
617  ofstream out;
618  out.open(outName);
619  for (unsigned int a=0; a<4; a++)
620  for (unsigned int b=0; b<iToCh[a].size(); b++)
621  {
622  const int ch = iToCh[a][b];
623  const int cellStat = chToCellStat[a][ch];
624  out <<Form("%2i %3i %i", a+8, ch, cellStat) <<endl;
625  }//a, b
626  out.close();
627  return;
628 }//PrintCellStat
629 
630 //----------------------------------------------------------------------------------------------
631 void PrintFitResults(const char* outName, map<int, int> iToCh[4], map<int, st_fitR> chToFitR[4])
632 {
633  ofstream out;
634  out.open(outName);
635  for (int a=0; a<4; a++)
636  for (unsigned int b=0; b<iToCh[a].size(); b++)
637  {
638  const int detId = a+8;
639  const int ch = iToCh[a][b];
640 
641  const int nRefit = chToFitR[a][ch].nRefit;
642  const float chi2 = chToFitR[a][ch].chi2;
643  const float mass = chToFitR[a][ch].mass;
644  const float massErr = chToFitR[a][ch].massErr;
645  const float width = chToFitR[a][ch].width;
646  const float widthErr = chToFitR[a][ch].widthErr;
647  out <<Form("%2i %3i %2i %7.3f %6.5f %6.5f %6.5f %6.5f",
648  detId,ch,nRefit,chi2,mass,massErr,width,widthErr) <<endl;
649  }
650  out.close();
651 
652  return;
653 }//PrintMapChToFitR
654 
655 //----------------------------------------------------------------------
656 void PrintGainCorr(const char* outName, map<int, float> chToGainCorr[4])
657 {
658  ofstream out;
659  out.open(outName);
660  for (int i=1; i<=2; i++) //Official FmsGainCorr format, I really hate this...
661  {
662  if (i==1) //NSTB dummies
663  {
664  for (int a=1; a<=6; a++)
665  {
666  if (a<=2) { for (int b=1; b<=49; b++) out <<Form("%i %i %2i %5.3f", i, a, b, 0.000) <<endl; }
667  else if (a<=4) { for (int b=1; b<=25; b++) out <<Form("%i %i %2i %5.3f", i, a, b, 0.000) <<endl; }
668  else if (a<=6) { for (int b=1; b<= 7; b++) out <<Form("%i %i %2i %5.3f", i, a, b, 0.000) <<endl; }
669  }
670  }
671  else if (i==2)
672  {
673  for (int a=0; a<4; a++)
674  {
675  const int maxCh = (a<2)?578:288;
676  for (int b=0; b<maxCh; b++)
677  {
678  const int ch = b+1;
679  const float gainCorr = chToGainCorr[a][ch];
680  out <<Form("%i %i %3i %5.3f", i, a+1, ch, gainCorr) <<endl;
681  }//b, ch
682  }//a, detId
683  }
684  }
685  out.close();
686  return;
687 }//PrintGainCorr
688 
689 //------------------------------------------------------------------------------------------
690 void PrintSkewMonitor(const char* outName, map<int, int>iToCh[4], map<int, int> chToSkew[4])
691 {
692  ofstream out;
693  out.open(outName);
694  for (unsigned int a=0; a<4; a++)
695  for (unsigned int b=0; b<iToCh[a].size(); b++)
696  {
697  const int ch = iToCh[a][b];
698  const int nSkew = chToSkew[a][ch];
699  out <<Form("%2i %3i %i", a+8, ch, nSkew) <<endl;
700  }//a, b
701  out.close();
702  return;
703 }//PrintCellStat
704 
705 //-------------------
706 void TestConvergence(
707  const int iIter,
708  map<int, int> iToCh[4],
709  map<int, int> chToCellStat[4],
710  const char* outPath = "./Iterations"
711  )
712 {
713  //Check if minimum # of iterations satisfied for convergence test
714  const int nIter = 3;
715  if (iIter < nIter) { cout <<"Require more iterations: skip the convervence test..." <<endl; return; }
716  else cout <<Form("Starting convergence test for iterations %i - %i...", iIter-nIter, iIter) <<endl;
717 
718  //To check N iterations you need N+1 set of gainCorr (ex. 3 iterations <-> 0-1, 1-2, and 2-3)
719  map<int, float> chToGainCorr[nIter+1][4];
720  map<int, st_fitR> chToFitR[nIter+1][4];
721  for (int i=0; i<=nIter; i++)
722  {
723  GetMapChToGainCorr(Form("%s/FmsGainCorr_%i.txt", outPath, (iIter-nIter)+i), chToGainCorr[i]);
724  GetMapChToFitR(Form("%s/out_fmsCalibFit_%i.txt", outPath, (iIter-nIter)+i), chToFitR[i]);
725  }
726 
727  //Test convergence
728  //-------------------------------------------
729 
730  const int convNReq = 3; //# of "tolerance successively satisfied" required to judge convergence
731  const float convTolM = 0.005; //Tolerance 1: allowed mass fluctuation WRT pi0 mass
732  const float convTolG = 0.035; //Tolerance 2: allowed gainCorr fluctuation by "ratio to the previous value"
733 
734  int nConv[4] = {0};
735  map<int, int> chToCellStatNext[4];
736  for (unsigned int a=0; a<4; a++) //detId
737  for (unsigned int b=0; b<iToCh[a].size(); b++) //ch
738  {
739  const int ch = iToCh[a][b];
740  int cellStat = chToCellStat[a][ch];
741 
742  if (cellStat == GOOD)
743  {
744  //1st judgment: btw adjacent iteration, by using mass fluctuation and gainCorr change
745  int convCounter = 0;
746  for (int i=0; i<nIter; i++)
747  {
748  const float massFitR = chToFitR[i][a][ch].mass;
749  if (chToGainCorr[i][a][ch] == 0. || massFitR == 0.) continue;
750 
751  const float ratioAdj = fabs(chToGainCorr[i][a][ch] - chToGainCorr[i+1][a][ch])/chToGainCorr[i][a][ch];
752  if ((fabs(massFitR - 0.1349766) < convTolM) && (ratioAdj < convTolG)) convCounter++;
753  }
754 
755  //2nd judgment: btw first and last iteration
756  if (convCounter >= convNReq)
757  {
758  const float gainCorr1st = chToGainCorr[0][a][ch];
759  const float gainCorrFin = chToGainCorr[nIter][a][ch];
760  const float ratioWide = fabs(gainCorr1st - gainCorrFin)/gainCorr1st;
761  if (ratioWide < convTolG)
762  {
763  cellStat = CONVERGED;
764  cout <<Form("Converged: %2i, %3i", a+8, ch) <<endl;
765  }
766  }
767  }//Cell status = good (not bad/hot/converged, keep going)
768 
769  if (cellStat == CONVERGED) nConv[a]++;
770  chToCellStatNext[a].insert(pair<int, int>(ch, cellStat));
771  }//a, b
772 
773  //Print new cellStat
774  //-------------------------------------------
775 
776  PrintCellStat(Form("FmsCellStatNew_%i.txt", iIter), iToCh, chToCellStatNext);
777  gSystem->Exec(Form("mv FmsCellStat.txt %s/FmsCellStat_%i.txt", outPath, iIter));
778  gSystem->Exec(Form("mv FmsCellStatNew_%i.txt FmsCellStat.txt", iIter));
779 
780  //Check convergence ratio
781  //-------------------------------------------
782 
783  for (int a=0; a<4; a++)
784  {
785  const int nCh = iToCh[a].size();
786  cout <<Form("detId=%2i: %3i/%3i (%6.4f)", a+8, nConv[a], nCh, (float)nConv[a]/nCh) <<endl;
787  }
788  const int nConvAll = nConv[0] + nConv[1] + nConv[2] + nConv[3];
789  const float rConvAll = (float)nConvAll/1264.;
790  cout <<Form("Total: %i/1264 (%6.4f)", nConvAll, rConvAll) <<endl;
791 
792  return;
793 }//TestConvergence