SPLifetime_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 // Class: Lifetime
3 // Plugin Type: analyzer (art v2_06_03)
4 // File: Lifetime_module.cc
5 //
6 // Generated at Mon May 29 09:34:51 2017 by Bruce Baller using cetskelgen
7 // from cetlib version v2_03_00.
8 ////////////////////////////////////////////////////////////////////////
9 
18 #include "fhiclcpp/ParameterSet.h"
20 
28 #include "art_root_io/TFileService.h"
29 #include "art_root_io/TFileDirectory.h"
30 #include "canvas/Persistency/Common/FindManyP.h"
31 #include "cetlib_except/exception.h"
32 
33 #include <regex>
34 
35 #include <fstream>
36 #include <sstream>
37 #include <iomanip>
38 #include <array>
39 
40 //#include "larsim/MCCheater/BackTracker.h"
41 
42 #include "TH1F.h"
43 #include "TH2F.h"
44 #include "TProfile.h"
45 #include "TCanvas.h"
46 
47 #define setHistTitles(hist,xtitle,ytitle) hist->GetXaxis()->SetTitle(xtitle); hist->GetYaxis()->SetTitle(ytitle);
48 #define appendToHistTitle(hist,str) hist->SetTitle((std::string(hist->GetTitle())+std::string(str)).c_str());
49 
50 //// apa = tpcMapping[tpc]
51 const std::array<size_t,13> tpcMapping = {{0,4,1,0,0,5,2,0,0,6,3,0,0}};
52 //// hist->GetXaxis()->SetBinLabel(iBin+1,apaLabels[iBin])
53 const std::array<std::string,6> apaLabels = {{
54  "APA-DaS-US/APA5",
55  "APA-DaS-MS/APA6",
56  "APA-DaS-DS/APA4",
57  "APA-RaS-US/APA3",
58  "APA-RaS-MS/APA2",
59  "APA-RaS-DS/APA1",
60  }};
61 
62 namespace nlana {
63  class SPLifetime;
64 }
65 
66 
68 public:
69  explicit SPLifetime(fhicl::ParameterSet const & p);
70  // The compiler-generated destructor is fine for non-base
71  // classes without bare pointers or other resource use.
72 
73  // Plugins should not be copied or assigned.
74  SPLifetime(SPLifetime const &) = delete;
75  SPLifetime(SPLifetime &&) = delete;
76  SPLifetime & operator = (SPLifetime const &) = delete;
77  SPLifetime & operator = (SPLifetime &&) = delete;
78 
79  // Required functions.
80  void analyze(art::Event const & e) override;
81 
82  // Selected optional functions.
83  void beginJob() override;
84  void endJob() override;
85  void reconfigure(fhicl::ParameterSet const & p);
86  void respondToOpenInputFile(art::FileBlock const & infileblock) override;
87 
88 private:
89 
91  double fChiCut;
92  std::vector<float> fChgCuts;
93  double fTicksPerBin; // 200 ticks * 0.5 us/tick = 0.1 ms
94  unsigned fMinBins;
95  unsigned fMinHits;
96  double fMinDTickSNR;
97  double fMinDWireSNR;
98  unsigned fMinHitsSNR;
99  int lastRun;
103  double bigLifeInv[12];
104  double bigLifeInvErr[12];
105  double bigLifeInvCnt[12];
106  double signalToNoise[12];
107  double signalToNoiseCnt[12];
108  unsigned int signalToNoiseClsCnt[12];
109 
110  TH1F *fLife;
111  TH2F *fLifeVTPC;
112  TH1F *fLifeInv;
114  TH1F *fChiDOF;
115  TH1F *fLifeInvCA;
116  TH1F *fLifeInvAC;
117 
118  TProfile *fLifeInv_E;
119  TProfile *fLifeInv_Angle;
120 
121  TH1F *fDriftTime;
123 
124  TH1F *fSNR;
125  TH2F *fSNRVTPC;
126 
127  TH1F *fAmplitudes;
128  TH1F *fNoise;
129  TH1F *fNoiseWide;
130 
131 };
132 
133 
135  :
136  EDAnalyzer(pset),
137  fInFilename("NoInFilenameFound"),
138  fIsRealData(true)
139 
140  // More initializers here.
141 {
142  reconfigure(pset);
143 }
144 
145 //--------------------------------------------------------------------
147 {
148  // Implementation of optional member function here.
149 
151  fLife = tfs->make<TH1F>("Life","Electron Lifetime for all APAs", 50, 0, 15);
152  setHistTitles(fLife,"Cluster Electron Lifetime [ms]", "Clusters / Bin");
153  fLifeVTPC = tfs->make<TH2F>("LifeVTPC","Electron Lifetime v. APA", 6,0.5,6.5,50, 0, 15.);
154  setHistTitles(fLifeVTPC,"","Cluster Electron Lifetime [ms]");
155  fLifeInv = tfs->make<TH1F>("LifeInv","LifeInv", 50, 0, 1);
156  fFracSelHits = tfs->make<TH1F>("FracSelHits","FracSelHits", 50, 0, 1);
157  fChiDOF = tfs->make<TH1F>("ChiDOF","ChiDOF", 80, 0, 80);
158  fLifeInvCA = tfs->make<TH1F>("LifeInvCA","LifeInv C to A", 50, 0, 1);
159  fLifeInvAC = tfs->make<TH1F>("LifeInvAC","LifeInv A to C", 50, 0, 1);
160 
161  fLifeInv_E = tfs->make<TProfile>("LifeInv_E","LifeInv_E", 20, 0, 40);
162  fLifeInv_Angle = tfs->make<TProfile>("LifeInv_Angle","LifeInv_Angle", 15, -1.5, 1.5);
163 
164  // initialize an invalid run number
165  lastRun = -1;
166  for(unsigned short tpc = 0; tpc < 12; ++tpc) {
167  bigLifeInv[tpc] = 0;
168  bigLifeInvErr[tpc] = 0;
169  bigLifeInvCnt[tpc] = 0;
170  signalToNoise[tpc] = 0;
171  signalToNoiseCnt[tpc] = 0;
172  signalToNoiseClsCnt[tpc] = 0;
173  }
174 
175  fDriftTime = tfs->make<TH1F>("DriftTime","Drift Time", 500, 0.,10.);
176  setHistTitles(fDriftTime,"Cluster Drift Time [ms]", "Clusters / Bin");
177  fDriftTimeVTPC = tfs->make<TH2F>("DriftTimeVTPC","Drift Time v. APA", 6,0.5,6.5,500,0.,10.);
178  setHistTitles(fDriftTimeVTPC,"","Cluster Drift Time [ms]");
179 
180  fSNR = tfs->make<TH1F>("SNR","Signal to Noise Ratio", 400, 0.,200);
181  setHistTitles(fSNR,"Signal to Noise Ratio", "Hits / Bin");
182  fSNRVTPC = tfs->make<TH2F>("SNRVTPC","Signal to Noise Ratio v. APA", 6,0.5,6.5,400,0.,200.);
183  setHistTitles(fSNRVTPC,"TPC Number","Signal to Noise Ratio");
184 
185  fAmplitudes = tfs->make<TH1F>("Amplitudes","Hit Amplitude", 4100, 0.,4100.);
186  setHistTitles(fAmplitudes,"Hit Amplitude [ADC]", "Hits / Bin");
187  fNoise = tfs->make<TH1F>("Noise","Wire Noise < 10 ADC", 2000, 0.,10.);
188  setHistTitles(fNoise,"RMS Noise [ADC]", "Hit Wires / Bin");
189  fNoiseWide = tfs->make<TH1F>("NoiseWide","Wire Noise", 2000, 0.,1000.);
190  setHistTitles(fNoiseWide,"RMS Noise [ADC]", "Hit Wires / Bin");
191 
192  for(size_t apa = 0; apa < 6; ++apa){
193  fLifeVTPC->GetXaxis()->SetBinLabel(apa+1,apaLabels.at(apa).c_str());
194  fDriftTimeVTPC->GetXaxis()->SetBinLabel(apa+1,apaLabels.at(apa).c_str());
195  fSNRVTPC->GetXaxis()->SetBinLabel(apa+1,apaLabels.at(apa).c_str());
196  }
197 
198 } // beginJob
199 
200 //--------------------------------------------------------------------
202 {
203  // Implementation of optional member function here.
204  fClusterModuleLabel = pset.get<std::string>("ClusterModuleLabel");
205  fChgCuts = pset.get<std::vector<float>>("ChgCuts", {0, 5});
206  fChiCut = pset.get<double>("ChiCut", 3);
207  fTicksPerBin = pset.get<double>("TicksPerBin");
208  fMinBins = pset.get<unsigned>("MinBins");
209  fMinHits = pset.get<unsigned>("MinHits");
210  fMinDTickSNR = pset.get<double>("MinDTickSNR");
211  fMinDWireSNR = pset.get<double>("MinDWireSNR");
212  fMinHitsSNR = pset.get<unsigned>("MinHitsSNR");
213  fDebugCluster = pset.get<int>("DebugCluster");
214 } // reconfigure
215 
216 //--------------------------------------------------------------------
218 {
219  std::ofstream purfile;
220  purfile.open("Lifetime_Run" + std::to_string(lastRun) + ".txt");
221  //purfile<<"Run, tpc, lifetime, error, count, S/N, num S/N clusters\n";
222  purfile<<"Run, tpc, lifetime, error, count, S/N, num S/N clusters, drift time\n";
223 
224  for(unsigned short tpc = 0; tpc < 12; ++tpc) {
225  if(bigLifeInvCnt[tpc] < 2) continue;
226  if(bigLifeInv[tpc] <= 0) continue;
227  bigLifeInv[tpc] /= bigLifeInvCnt[tpc];
228  bigLifeInvErr[tpc] = bigLifeInvErr[tpc] - bigLifeInvCnt[tpc] * bigLifeInv[tpc] * bigLifeInv[tpc];
229  if(bigLifeInvErr[tpc] < 0) continue;
230  bigLifeInvErr[tpc] = sqrt(bigLifeInvErr[tpc] / (bigLifeInvCnt[tpc] - 1));
231  // convert to error on the mean
232  bigLifeInvErr[tpc] /= sqrt(bigLifeInvCnt[tpc]);
233  float life = 0;
234  if(1/bigLifeInv[tpc] != 0) life = 1 / bigLifeInv[tpc];
235  float lifeErr = life * bigLifeInvErr[tpc] / bigLifeInv[tpc];
236  float sn = -1;
237  if(signalToNoiseCnt[tpc] > 100) sn = signalToNoise[tpc] / signalToNoiseCnt[tpc];
238  purfile<<lastRun<<", "<<tpc<<", "<<std::fixed<<std::setprecision(2)<<life<<", "<<lifeErr<<", "<<(int)bigLifeInvCnt[tpc];
239  purfile<<", "<<std::setprecision(1)<<sn<<", "<<signalToNoiseClsCnt[tpc];
240 
241  // Now do drift time
242  size_t apa = tpcMapping.at(tpc);
243  if (apa == 0) continue;
244  size_t nBinsY = fDriftTimeVTPC->GetNbinsY();
245  float driftTime = -1.;
246  for (int iBin=nBinsY; iBin >=0; iBin--)
247  {
248  if (fDriftTimeVTPC->GetBinContent(apa,iBin) > 1)
249  {
250  driftTime = fDriftTimeVTPC->GetYaxis()->GetBinCenter(iBin);
251  break;
252  }
253  }
254  purfile<<", "<<std::setprecision(2)<<driftTime;
255 
256  purfile<<"\n";
257  }
258  purfile.close();
259 
260  // Now for images
261  TCanvas * canvas = new TCanvas("canvas_SPLifetime");
262  canvas->SetLogz();
263  canvas->SetBottomMargin(0.13);
264  canvas->SetRightMargin(0.12);
265  std::string imageFileName;
266 
267  // Get filename in format p3s wants
268  // "run": "run003907_0001_dl05",
269  unsigned runNum = lastRun;
270  unsigned fileNum = 1;
271  unsigned dlNum = 5;
272  if (fIsRealData)
273  {
274  static const std::string patternString = "run(\\d+)_(\\d+)_dl(\\d+)";
275  static const std::regex pattern(patternString);
276  std::smatch patternMatches;
277  const bool foundMatch = std::regex_search(fInFilename,patternMatches,pattern);
278  if(foundMatch)
279  {
280  std::cout << "filename: " << fInFilename << " match: " << patternMatches[0] << " run: " << patternMatches[1] << " file: " << patternMatches[2] << " dl: " << patternMatches[3] << std::endl;
281  runNum = std::stoi(patternMatches[1]);
282  fileNum = std::stoi(patternMatches[2]);
283  dlNum = std::stoi(patternMatches[3]);
284  }
285  else
286  {
287  //throw cet::exception("InputFilenameError")
288  // <<"Couldn't parse input filename: '"<<fInFilename<<"' with regex '"<<patternString<<"'";
289  std::cout <<"Error: couldn't parse input filename: '"<<fInFilename<<"' with regex '"<<patternString<<"'\n";
290  }
291  }
292 
293  std::stringstream infileNameStrStream;
294  infileNameStrStream << "run";
295  infileNameStrStream << std::setfill('0') << std::setw(6) << runNum;
296  infileNameStrStream << std::setw(0) << '_';
297  infileNameStrStream << std::setw(4) << fileNum;
298  const std::string identifierNoDL = infileNameStrStream.str();
299  infileNameStrStream << std::setw(0) << "_dl";
300  infileNameStrStream << std::setw(2) << dlNum;
301  const std::string identifierDL = infileNameStrStream.str();
302 
303  std::cout << "identifierDL: " << identifierDL << std::endl;
304  std::cout << "identifierNoDL: " << identifierNoDL << std::endl;
305  const std::string identifierTitle = " " + identifierDL;
306 
307  //std::string identifierBase = infilenameStripped;
308  //identifierBase.erase(identifierBase.rfind("_dl"));
309  //std::cout << "identifierBase: '"<<identifierBase<<"'";
310  //std::string dlStr = infilenameStripped;
311  //dlStr.erase(0,dlStr.rfind("_dl")+3);
312  //std::cout << "dlStr: '"<<dlStr<<"'";
313 
314  //// summary json file
315  // fn should be like run003907_0001_purity_summary.json
316  std::string summary_filename = identifierNoDL+"_purity_summary.json";
317  std::string filelist_filename = identifierNoDL+"_purity_FileList.json";
318 
319  std::ofstream summaryfile;
320  summaryfile.open(summary_filename);
321  summaryfile << "[\n {\n \"run\": \"" << identifierDL << "\",\n"
322  << " \"Type\": \"purity\"\n }\n]\n";
323  summaryfile.close();
324 
325  // file list json file
326  std::ofstream filelistfile;
327  filelistfile.open(filelist_filename);
328  filelistfile << "[\n {\n \"Category\": \"Purity Monitor\",\n \"Files\": {\n \"Cluster Drift Time\": \"";
329 
330  imageFileName = "driftVTPC_";
331  imageFileName += identifierNoDL;
332  imageFileName += ".png";
333  appendToHistTitle(fDriftTimeVTPC,identifierTitle);
334  fDriftTimeVTPC->SetStats(false);
335  fDriftTimeVTPC->GetXaxis()->SetLabelSize(0.050);
336  fDriftTimeVTPC->Draw("colz");
337  canvas->SaveAs(imageFileName.c_str());
338  filelistfile << imageFileName<<",";
339 
340  imageFileName = "driftVTPC_zoom_";
341  imageFileName += identifierNoDL;
342  imageFileName += ".png";
343  std::string originalTitle = fDriftTimeVTPC->GetTitle();
344  fDriftTimeVTPC->SetTitle((originalTitle+" From 0 to 4 ms").c_str());
345  fDriftTimeVTPC->GetYaxis()->SetRangeUser(0,4);
346  fDriftTimeVTPC->Draw("colz");
347  canvas->SaveAs(imageFileName.c_str());
348  fDriftTimeVTPC->SetTitle(originalTitle.c_str());
349  filelistfile << imageFileName;
350 
351  filelistfile << "\",\n";
352 
353  // Now e lifetime
354  filelistfile << " \"Purity\": \"";
355  imageFileName = "purity_";
356  imageFileName += identifierNoDL;
357  imageFileName += ".png";
358  appendToHistTitle(fLife,identifierTitle);
359  fLife->Draw();
360  canvas->SaveAs(imageFileName.c_str());
361  filelistfile << imageFileName<<",";
362 
363  canvas->SetLogz(false);
364  imageFileName = "purityVTPC_";
365  imageFileName += identifierNoDL;
366  imageFileName += ".png";
367  appendToHistTitle(fLifeVTPC,identifierTitle);
368  fLifeVTPC->SetStats(false);
369  fLifeVTPC->GetXaxis()->SetLabelSize(0.050);
370  fLifeVTPC->Draw("colz");
371  canvas->SaveAs(imageFileName.c_str());
372  filelistfile << imageFileName;
373  canvas->SetLogz();
374 
375  filelistfile << "\",\n";
376 
377  // Now SNR
378  filelistfile << " \"SNR\": \"";
379  imageFileName = "snr_";
380  imageFileName += identifierNoDL;
381  imageFileName += ".png";
382  canvas->SetLogy(true);
383  appendToHistTitle(fSNR,identifierTitle);
384  fLife->Draw();
385  fSNR->Draw();
386  canvas->SaveAs(imageFileName.c_str());
387  canvas->SetLogy(false);
388  filelistfile << imageFileName<<",";
389 
390  imageFileName = "snrVTPC_";
391  imageFileName += identifierNoDL;
392  imageFileName += ".png";
393  appendToHistTitle(fSNRVTPC,identifierTitle);
394  fSNRVTPC->SetStats(false);
395  fSNRVTPC->GetXaxis()->SetLabelSize(0.050);
396  fSNRVTPC->Draw("colz");
397  canvas->SaveAs(imageFileName.c_str());
398  filelistfile << imageFileName<<",";
399 
400  canvas->SetLogy(true);
401  imageFileName = "noise_";
402  imageFileName += identifierNoDL;
403  imageFileName += ".png";
404  appendToHistTitle(fNoise,identifierTitle);
405  fNoise->Draw();
406  canvas->SaveAs(imageFileName.c_str());
407  filelistfile << imageFileName<<",";
408 
409  imageFileName = "noiseWide_";
410  imageFileName += identifierNoDL;
411  imageFileName += ".png";
412  appendToHistTitle(fNoiseWide,identifierTitle);
413  fNoiseWide->Draw();
414  canvas->SaveAs(imageFileName.c_str());
415  filelistfile << imageFileName<<",";
416 
417  imageFileName = "amplitude_";
418  imageFileName += identifierNoDL;
419  imageFileName += ".png";
420  appendToHistTitle(fAmplitudes,identifierTitle);
421  fAmplitudes->Draw();
422  canvas->SaveAs(imageFileName.c_str());
423  filelistfile << imageFileName<<",";
424 
425  imageFileName = "amplitude_zoom_";
426  imageFileName += identifierNoDL;
427  imageFileName += ".png";
428  originalTitle = fAmplitudes->GetTitle();
429  fAmplitudes->SetTitle((originalTitle+" From 0 to 500 ADC").c_str());
430  fAmplitudes->GetXaxis()->SetRangeUser(0,500);
431  fAmplitudes->Draw();
432  canvas->SaveAs(imageFileName.c_str());
433  filelistfile << imageFileName;
434  canvas->SetLogy(false);
435 
436  filelistfile << "\"\n }\n }\n]\n";
437  filelistfile.close();
438  delete canvas;
439 
440 } // endJob
441 
442 //--------------------------------------------------------------------
444 {
445  fInFilename = infileblock.fileName();
446 } // respondToOpenInputFile
447 
448 //--------------------------------------------------------------------
450 {
451 
452 // int event = evt.id().event();
453  int run = evt.run();
454 // int subrun = evt.subRun();
455  fIsRealData = evt.isRealData();
456 
457  if(lastRun < 0) lastRun = run;
458 
459  if(run != lastRun) mf::LogVerbatim("LIFE")<<"The run number has changed from "<<lastRun<<" to "<<run<<" This might not be good...";
460 
461  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(evt);
462  double msPerTick = 1E-6 * sampling_rate(clockData);
463 
464 
465  art::ValidHandle<std::vector<recob::Cluster>> clsVecHandle = evt.getValidHandle<std::vector<recob::Cluster>>(fClusterModuleLabel);
466  art::FindManyP<recob::Hit> clsHitsFind(clsVecHandle, evt, fClusterModuleLabel);
467  art::ValidHandle<std::vector<recob::Wire>> wireVecHandle = evt.getValidHandle<std::vector<recob::Wire>>("caldata");
468 
469 // bool prt = false;
470 
471 
472  for(unsigned int icl = 0; icl < clsVecHandle->size(); ++icl) {
473  art::Ptr<recob::Cluster> cls = art::Ptr<recob::Cluster>(clsVecHandle, icl);
474  // only consider the collection plane
475  if(cls->Plane().Plane != 2) continue;
476 // prt = (fDebugCluster >= 0 && icl == (unsigned int)fDebugCluster);
477  float sTick = cls->StartTick();
478  float eTick = cls->EndTick();
479  if(sTick > eTick) std::swap(sTick, eTick);
480  float dTick = eTick - sTick;
481  // Get the hits
482  std::vector<art::Ptr<recob::Hit> > clsHits;
483  clsHitsFind.get(icl, clsHits);
484  if(clsHits.size() == 0) continue;
485  unsigned short tpc = clsHits[0]->WireID().TPC;
486  fDriftTime->Fill(dTick*msPerTick);
487  fDriftTimeVTPC->Fill(tpcMapping.at(tpc),dTick*msPerTick);
488  unsigned short nhist = 1 + (unsigned short)(dTick / fTicksPerBin);
489  if(nhist < fMinBins) continue;
490  if(clsHits.size() < fMinHits) continue;
491 /*
492  if(prt) {
493  auto& sht = clsHits[0];
494  std::cout<<"Cls "<<icl<<" "<<sht->WireID().TPC<<":"<<sht->WireID().Plane<<":"<<sht->WireID().Wire<<":"<<(int)sht->PeakTime();
495  auto& eht = clsHits[clsHits.size()-1];
496  std::cout<<" "<<eht->WireID().TPC<<":"<<eht->WireID().Plane<<":"<<eht->WireID().Wire<<":"<<(int)eht->PeakTime();
497  std::cout<<" sTick "<<(int)sTick<<" "<<(int)eTick<<" nhits "<<clsHits.size()<<" nhist "<<nhist<<"\n";
498  }
499 */
500  // Find the average and maximum charge of these histograms
501  std::vector<double> tck(nhist), ave(nhist), cnt(nhist), err(nhist);
502  std::vector<float> minChg(nhist, 0);
503  std::vector<float> maxChg(nhist, 10000);
504  for(unsigned short nit = 0; nit < 2; ++nit) {
505  for(unsigned short ihist = 0; ihist < nhist; ++ihist) {
506  tck[ihist] = 0;
507  ave[ihist] = 0;
508  cnt[ihist] = 0;
509  err[ihist] = 0;
510  } // ihist
511  // Sum to get the (truncated) average
512  for(auto& pht : clsHits) {
513  unsigned short ihist = (pht->PeakTime() - sTick) / fTicksPerBin;
514  if(ihist > nhist - 1) continue;
515  float chg = pht->Integral();
516  if(chg < minChg[ihist] || chg > maxChg[ihist]) continue;
517  tck[ihist] += pht->PeakTime() - sTick;
518  ave[ihist] += chg;
519  err[ihist] += chg * chg;
520  ++cnt[ihist];
521  } // ii
522  for(unsigned short ihist = 0; ihist < nhist; ++ihist) if(cnt[ihist] > 0) {
523  tck[ihist] /= cnt[ihist];
524  ave[ihist] /= cnt[ihist];
525  }
526  if(nit == 0) {
527  // Calculate a max charge cut on the first iteration
528  for(unsigned short ihist = 0; ihist < nhist; ++ihist) {
529  maxChg[ihist] = 0;
530  if(cnt[ihist] < 5) continue;
531  maxChg[ihist] = fChgCuts[1] * ave[ihist];
532  minChg[ihist] = fChgCuts[0] * ave[ihist];
533 // if(prt) std::cout<<ihist<<" Min "<<(int)minChg[ihist]<<" max "<<(int)maxChg[ihist]<<"\n";
534  } // ihist
535  } else {
536  // Calculate the error on the average on the second iteration
537  for(unsigned short ihist = 0; ihist < nhist; ++ihist) {
538  if(cnt[ihist] < 3) continue;
539  double arg = err[ihist] - cnt[ihist] * ave[ihist] * ave[ihist];
540  if(arg < 0) {
541  cnt[ihist] = 0;
542  continue;
543  }
544  // calculate rms
545  err[ihist] = sqrt(arg / (cnt[ihist] - 1));
546  // convert to error on the mean
547  err[ihist] /= sqrt(cnt[ihist]);
548  } // ihist
549  } // second iteration
550  } // nit
551 
552  // require a minimum count in each histogram
553  unsigned short nok = 0;
554  for(auto& icnt : cnt) if(icnt > 4) ++nok;
555  if(nok < 5) {
556 // if(prt) std::cout<<" failed nok cut "<<nok<<" Need at least 4 \n";
557  continue;
558  }
559 /*
560  if(prt) {
561  for(unsigned short ihist = 0; ihist < nhist; ++ihist) {
562  float xx = (ihist + 0.5) * fTicksPerBin + sTick;
563  std::cout<<"ihist "<<ihist<<" tick "<<(int)xx<<" ave "<<(int)ave[ihist]<<" +/- "<<(int)err[ihist]<<" cnt "<<(int)cnt[ihist]<<"\n";
564  } // ihist
565  }
566 */
567  // fit to find the 1/lifetime
568  double sum = 0.;
569  double sumx = 0.;
570  double sumy = 0.;
571  double sumxy = 0.;
572  double sumx2 = 0.;
573  double sumy2 = 0.;
574  double xx, yy, wght, arg;
575  double fitcnt = 0;
576 
577  for(unsigned short ihist = 0; ihist < nhist; ++ihist) {
578  if(cnt[ihist] < 3) continue;
579  if(err[ihist] == 0) continue;
580  xx = (tck[ihist] - tck[0]) * msPerTick;
581  yy = log(ave[ihist]);
582  // error on log(x) = dx / x
583  arg = ave[ihist] / err[ihist];
584  wght = arg * arg;
585  sum += wght;
586  sumx += wght * xx;
587  sumy += wght * yy;
588  sumx2 += wght * xx * xx;
589  sumxy += wght * xx * yy;
590  sumy2 += wght * yy * yy;
591  ++fitcnt;
592  } // ihist
593  // calculate coefficients
594  double delta = sum * sumx2 - sumx * sumx;
595  if(delta == 0.) continue;
596  double A = (sumx2 * sumy - sumx * sumxy) / delta;
597  // slope = 1 / lifetime
598  double B = (sumxy * sum - sumx * sumy) / delta;
599  if(B > 0) continue;
600  // calculate the error
601  double ndof = fitcnt - 2;
602  double varnce = (sumy2 + A*A*sum + B*B*sumx2 - 2 * (A*sumy + B*sumxy - A*B*sumx)) / ndof;
603  if(varnce == 0) continue;
604 // double BErr = sqrt(varnce * sum / delta);
605 // if(prt) std::cout<<"B "<<B<<" "<<BErr;
606 
607  double lifeInv = -B;
608 // double lifeInvErr = BErr / (B * B) ;
609 
610  // calculate chisq
611  double chi = 0;
612  for(unsigned short ihist = 0; ihist < nhist; ++ihist) {
613  if(cnt[ihist] < 3) continue;
614  if(err[ihist] == 0) continue;
615  xx = (tck[ihist] - tck[0]) * msPerTick;
616  yy = exp(A - xx * lifeInv);
617  arg = (yy - ave[ihist]) / err[ihist];
618  chi += arg * arg;
619 // if(prt) std::cout<<"chk "<<ihist<<" xx "<<xx<<" yy "<<yy<<" ave "<<ave[ihist]<<" arg "<<arg<<"\n";
620  }
621  chi /= ndof;
622 // if(prt) std::cout<<tpc<<" lifeInv "<<lifeInv<<" +/- "<<lifeInvErr<<" chi "<<chi<<"\n";
623  fChiDOF->Fill(chi);
624  if(chi > fChiCut) continue;
625  ++bigLifeInvCnt[tpc];
626  bigLifeInv[tpc] += lifeInv;
627  bigLifeInvErr[tpc] += lifeInv * lifeInv;
628  fLifeInv->Fill(lifeInv);
629  fLife->Fill(1./lifeInv);
630  fLifeVTPC->Fill(tpcMapping.at(tpc),1./lifeInv);
631 
632  double selHits = 0;
633  for(auto& hcnt : cnt) selHits += hcnt;
634  selHits /= (double)(clsHits.size());
635  fFracSelHits->Fill(selHits);
636 
637  fLifeInv_Angle->Fill(cls->StartAngle(), lifeInv);
638  } // icl
639 
640  std::vector<std::pair<unsigned int, float>> chanPedRMS;
641 // std::cout << "n wire data: "<<wireVecHandle->size() << std::endl;
642  for(unsigned int witer = 0; witer < wireVecHandle->size(); ++witer) {
643  art::Ptr<recob::Wire> thisWire(wireVecHandle, witer);
644  const recob::Wire::RegionsOfInterest_t& signalROI = thisWire->SignalROI();
645  for(const auto& range : signalROI.get_ranges()) {
646  const std::vector<float>& signal = range.data();
647 // std::cout << "channel: "<<thisWire->Channel()<<" range begin: " << range.begin_index() << " range size: "<<range.size()<<"signal length: " << signal.size() << std::endl;
648  if(signal.size() != 1) continue;
649  // protect against unrealistic values
650  float rms = signal[0];
651  if(rms < 0.001) rms = 0.001;
652  chanPedRMS.push_back(std::make_pair(thisWire->Channel(), rms));
653 // std::cout << "channel: "<<thisWire->Channel()<<" rms: " << rms << std::endl;
654  }
655  }// witer
656 
657  // calculate S/N using shallow angle clusters
658  for(unsigned int icl = 0; icl < clsVecHandle->size(); ++icl) {
659  art::Ptr<recob::Cluster> cls = art::Ptr<recob::Cluster>(clsVecHandle, icl);
660  // only consider the collection plane
661  if(cls->Plane().Plane != 2) continue;
662  float dTick = std::abs(cls->StartTick() - cls->EndTick());
663  if(dTick < fMinDTickSNR) continue;
664  float dWire = std::abs(cls->StartWire() - cls->EndWire());
665  if(dWire < fMinDWireSNR) continue;
666  // Get the hits
667  std::vector<art::Ptr<recob::Hit> > clsHits;
668  clsHitsFind.get(icl, clsHits);
669  if(clsHits.size() < fMinHitsSNR) continue;
670  unsigned short tpc = clsHits[0]->WireID().TPC;
671  ++signalToNoiseClsCnt[tpc];
672 // float aveSN = 0;
673 // float cnt = 0;
674  for(auto& hit : clsHits) {
675  float pedRMS = -1;
676  for(auto& chrms : chanPedRMS) {
677  if(chrms.first != hit->Channel()) continue;
678  pedRMS = chrms.second;
679  break;
680  } // chrms
681  if(pedRMS < 0) continue;
682  float snr = hit->PeakAmplitude() / pedRMS;
683  //std::cout<<"SNR "<<(int)snr << " S: " << hit->PeakAmplitude() << " N: "<< pedRMS <<"\n";
684  signalToNoise[tpc] += snr;
685  ++signalToNoiseCnt[tpc];
686  fAmplitudes->Fill(hit->PeakAmplitude());
687  fNoise->Fill(pedRMS);
688  fNoiseWide->Fill(pedRMS);
689  fSNR->Fill(snr);
690  fSNRVTPC->Fill(tpcMapping.at(tpc),snr);
691 // aveSN += sn;
692 // ++cnt;
693  } // hit
694 /*
695  if(cnt == 0) continue;
696  aveSN /= cnt;
697  std::cout<<" aveSN "<<aveSN<<" cnt "<<(int)cnt<<"\n";
698 */
699  } // icl
700 
701 } // analyze
702 
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
double rms(sqlite3 *db, std::string const &table_name, std::string const &column_name)
Definition: statistics.cc:40
std::string string
Definition: nybbler.cc:12
#define appendToHistTitle(hist, str)
void respondToOpenInputFile(art::FileBlock const &infileblock) override
float StartWire() const
Returns the wire coordinate of the start of the cluster.
Definition: Cluster.h:286
const range_list_t & get_ranges() const
Returns the internal list of non-void ranges.
float EndTick() const
Returns the tick coordinate of the end of the cluster.
Definition: Cluster.h:342
geo::PlaneID Plane() const
Returns the plane ID this cluster lies on.
Definition: Cluster.h:744
EDAnalyzer(fhicl::ParameterSet const &pset)
Definition: EDAnalyzer.h:25
void endJob() override
float StartAngle() const
Returns the starting angle of the cluster.
Definition: Cluster.h:475
Q_EXPORT QTSManip setprecision(int p)
Definition: qtextstream.h:343
art framework interface to geometry description
bool isRealData() const
T abs(T value)
const double e
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:67
void swap(Handle< T > &a, Handle< T > &b)
raw::ChannelID_t Channel() const
Returns the ID of the channel (or InvalidChannelID)
Definition: Wire.h:231
T get(std::string const &key) const
Definition: ParameterSet.h:271
std::string const & fileName() const
Definition: FileBlock.cc:29
const std::array< std::string, 6 > apaLabels
ValidHandle< PROD > getValidHandle(InputTag const &tag) const
Definition: DataViewImpl.h:441
p
Definition: test.py:223
const RegionsOfInterest_t & SignalROI() const
Returns the list of regions of interest.
Definition: Wire.h:228
const std::array< size_t, 13 > tpcMapping
Definition: SNSlice.h:7
unsigned int signalToNoiseClsCnt[12]
RunNumber_t run() const
Definition: DataViewImpl.cc:71
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
Definition of data types for geometry description.
void err(const char *fmt,...)
Definition: message.cpp:226
Detector simulation of raw signals on wires.
Q_EXPORT QTSManip setw(int w)
Definition: qtextstream.h:331
std::string fClusterModuleLabel
std::vector< float > fChgCuts
Declaration of signal hit object.
SPLifetime & operator=(SPLifetime const &)=delete
std::string pattern
Definition: regex_t.cc:35
Declaration of basic channel signal object.
#define setHistTitles(hist, xtitle, ytitle)
void reconfigure(fhicl::ParameterSet const &p)
TCEvent evt
Definition: DataStructs.cxx:7
SPLifetime(fhicl::ParameterSet const &p)
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
void analyze(art::Event const &e) override
float StartTick() const
Returns the tick coordinate of the start of the cluster.
Definition: Cluster.h:297
Q_EXPORT QTSManip setfill(int f)
Definition: qtextstream.h:337
std::string to_string(ModuleType const mt)
Definition: ModuleType.h:34
QTextStream & endl(QTextStream &s)
void beginJob() override
float EndWire() const
Returns the wire coordinate of the end of the cluster.
Definition: Cluster.h:329