LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
LEDCalibrationAna_module.cc
Go to the documentation of this file.
1 // -*- mode: c++; c-basic-offset: 2; -*-
2 // Ben Jones, MIT, 2013
3 //
4 // This ana module extracts pedestals and gains from
5 // LED calibration run data (incomplete)
6 //
7 
8 // LArSoft includes
18 
19 // Framework includes
25 #include "art_root_io/TFileService.h"
26 #include "fhiclcpp/ParameterSet.h"
27 
28 // ROOT includes
29 #include "TF1.h"
30 #include "TH1.h"
31 #include <TTree.h>
32 
33 // C++ Includes
34 #include "math.h"
35 #include <cstring>
36 #include <iostream>
37 #include <map>
38 #include <sstream>
39 
40 namespace opdet {
41 
43  public:
44  // Standard constructor and destructor for an ART module.
46 
47  void endJob();
48 
49  // The analyzer routine, called once per event.
50  void analyze(const art::Event&);
51 
52  private:
53  // The parameters we'll read from the .fcl file.
54  std::string fInputModule; // Input tag for OpDet collection
55  uint32_t fTriggerChannel;
57  float fMaxTimeMean;
59  float fAreaDivs;
60  float fAreaMin;
61  float fAreaMax;
63 
67  TTree* fPulseTree;
69  Float_t fPeak;
70  Float_t fPedRMS;
71  Float_t fPedMean;
72  Float_t fArea;
73  Float_t fTBegin;
74  Float_t fTEnd;
75  Float_t fTMax;
76  Float_t fOffset;
77  Int_t fEventID;
78  Int_t fRunID;
79  Int_t fChannel;
80  Int_t fShaper;
81 
82  uint32_t ShaperToChannel(uint32_t Shaper);
83 
85 
86  std::map<uint32_t, std::vector<double>> fAreas;
87  };
88 
89 }
90 
91 namespace opdet {
92 
93  //-----------------------------------------------------------------------
94  // Constructor
97  {
98  // Indicate that the Input Module comes from .fcl
99  fInputModule = pset.get<std::string>("InputModule");
100  fTriggerChannel = pset.get<uint32_t>("TriggerChannel");
101  fTriggerDelay = pset.get<uint32_t>("TriggerDelay");
102  fCoincThreshold = pset.get<float>("CoincThreshold");
103  fMaxTimeThresh = pset.get<float>("MaxTimeThresh");
104  fMaxTimeMean = pset.get<float>("MaxTimeMean");
105  fAreaMin = pset.get<float>("AreaMin");
106  fAreaMax = pset.get<float>("AreaMax");
107  fAreaDivs = pset.get<float>("AreaDivs");
108  fMakeNonCoincTree = pset.get<bool>("MakeNonCoincTree");
109 
112 
114 
115  fPulseTree = tfs->make<TTree>("fPulseTree", "fPulseTree");
116  fPulseTree->Branch("Area", &fArea, "Area/F");
117  fPulseTree->Branch("Peak", &fPeak, "Peak/F");
118  fPulseTree->Branch("TBegin", &fTBegin, "TBegin/F");
119  fPulseTree->Branch("TEnd", &fTEnd, "TEnd/F");
120  fPulseTree->Branch("TMax", &fTMax, "TMax/F");
121  fPulseTree->Branch("Channel", &fChannel, "Channel/I");
122  fPulseTree->Branch("Shaper", &fShaper, "Shaper/I");
123  fPulseTree->Branch("PedMean", &fPedMean, "PedMean/F");
124  fPulseTree->Branch("PedRMS", &fPedRMS, "PedRMS/F");
125  fPulseTree->Branch("Offset", &fOffset, "Offset/F");
126  fPulseTree->Branch("EventID", &fEventID, "EventID/I");
127  fPulseTree->Branch("RunID", &fRunID, "RunID/I");
128 
129  fPulseTreeNonCoinc = tfs->make<TTree>("fPulseTreeNonCoinc", "fPulseTreeNonCoinc");
130  fPulseTreeNonCoinc->Branch("Area", &fArea, "Area/F");
131  fPulseTreeNonCoinc->Branch("Peak", &fPeak, "Peak/F");
132  fPulseTreeNonCoinc->Branch("TBegin", &fTBegin, "TBegin/F");
133  fPulseTreeNonCoinc->Branch("TEnd", &fTEnd, "TEnd/F");
134  fPulseTreeNonCoinc->Branch("TMax", &fTMax, "TMax/F");
135  fPulseTreeNonCoinc->Branch("Channel", &fChannel, "Channel/I");
136  fPulseTreeNonCoinc->Branch("Shaper", &fShaper, "Shaper/I");
137  fPulseTreeNonCoinc->Branch("PedMean", &fPedMean, "PedMean/F");
138  fPulseTreeNonCoinc->Branch("PedRMS", &fPedRMS, "PedRMS/F");
139  fPulseTreeNonCoinc->Branch("EventID", &fEventID, "EventID/I");
140  fPulseTreeNonCoinc->Branch("RunID", &fRunID, "RunID/I");
141  }
142 
143  //-----------------------------------------------------------------------
145  {
147 
148  for (auto it = fAreas.begin(); it != fAreas.end(); ++it) {
149  uint32_t Channel = it->first;
150 
151  std::stringstream histname;
152  histname.flush();
153  histname << "ch" << Channel << "area";
154 
155  TH1D* HistArea = tfs->make<TH1D>(
156  histname.str().c_str(), histname.str().c_str(), fAreaDivs, fAreaMin, fAreaMax);
157 
158  for (size_t j = 0; j != it->second.size(); ++j) {
159  HistArea->Fill(it->second.at(j));
160  }
161 
162  std::stringstream fitname;
163  fitname.flush();
164  fitname << "ch" << Channel << "fit";
165 
166  double Max = HistArea->GetMaximum();
167  double Mid = HistArea->GetBinContent(fAreaDivs / 2.);
168 
169  TF1* GausFit = new TF1(fitname.str().c_str(), "gaus(0)+gaus(3)+gaus(6)", fAreaMin, fAreaMax);
170 
171  GausFit->SetParameters(Mid,
172  (fAreaMin + fAreaMax) / 2.,
173  (fAreaMax - fAreaMin) / 2.,
174  Max,
175  0,
176  (fAreaMin + fAreaMax) / 8.,
177  Max / 5.,
178  0,
179  (fAreaMin + fAreaMax) / 4.);
180 
181  GausFit->SetParLimits(0, 0, 1.1 * Max);
182  GausFit->SetParLimits(1, 0, fAreaMax);
183  GausFit->SetParLimits(2, 0, fAreaMax);
184 
185  GausFit->SetParLimits(3, 0, 1.1 * Max);
186  GausFit->FixParameter(4, 0);
187  GausFit->SetParLimits(5, 0, (fAreaMin + fAreaMax) / 2.);
188 
189  GausFit->SetParLimits(6, 0, 1.1 * Max);
190  GausFit->FixParameter(7, 0);
191  GausFit->SetParLimits(8, 0, (fAreaMin + fAreaMax) / 2.);
192 
193  HistArea->Fit(GausFit);
194 
195  double Mean = GausFit->GetParameter(1);
196  double Width = GausFit->GetParameter(2);
197 
198  double MeanErr = GausFit->GetParError(1);
199  double WidthErr = GausFit->GetParError(2);
200 
201  double NPE = pow(Mean, 2) / pow(Width, 2);
202  double SPEScale = Mean / NPE;
203 
204  double NPEError = NPE * pow(2. * (pow(MeanErr / Mean, 2) + pow(WidthErr / Width, 2)), 0.5);
205  double SPEError = SPEScale * pow(2. * pow(WidthErr / Width, 2) + pow(MeanErr / Mean, 2), 0.5);
206 
207  std::cout << "Channel " << Channel << ":\tSPE Scale \t" << SPEScale << "\t +/- \t" << SPEError
208  << ",\t NPE \t" << NPE << "\t +/- \t" << NPEError << std::endl;
209  }
210  }
211 
212  //-----------------------------------------------------------------------
214  {
215  auto const clock_data =
217 
218  fRunID = evt.run();
219  fEventID = evt.event();
220 
221  // Create a handle for our vector of pulses
222  art::Handle<std::vector<raw::OpDetWaveform>> OpDetWaveformHandle;
223 
224  // Read in WaveformHandle
225  evt.getByLabel(fInputModule, OpDetWaveformHandle);
226 
227  std::map<uint32_t, std::vector<int>> OrgOpDigitByChannel;
228 
229  for (size_t i = 0; i != OpDetWaveformHandle->size(); ++i) {
230  OrgOpDigitByChannel[ShaperToChannel(OpDetWaveformHandle->at(i).ChannelNumber())].push_back(i);
231  }
232 
233  std::vector<uint32_t> FrameNumbersForTrig;
234  std::vector<uint32_t> TimeSlicesForTrig;
235 
236  for (size_t i = 0; i != OrgOpDigitByChannel[fTriggerChannel].size(); ++i) {
237  double TimeStamp =
238  OpDetWaveformHandle->at(OrgOpDigitByChannel[fTriggerChannel][i]).TimeStamp();
239  uint32_t Frame = clock_data.OpticalClock().Frame(TimeStamp);
240  uint32_t TimeSlice = clock_data.OpticalClock().Sample(TimeStamp);
241  FrameNumbersForTrig.push_back(Frame);
242  TimeSlicesForTrig.push_back(TimeSlice);
243  }
244 
245  for (size_t i = 0; i != OpDetWaveformHandle->size(); ++i) {
246  double TimeStamp = OpDetWaveformHandle->at(i).TimeStamp();
247  uint32_t Frame = clock_data.OpticalClock().Frame(TimeStamp);
248  uint32_t TimeSlice = clock_data.OpticalClock().Sample(TimeStamp);
249  fShaper = OpDetWaveformHandle->at(i).ChannelNumber();
251 
252  if (uint32_t(fChannel) != fTriggerChannel) {
253  for (size_t j = 0; j != FrameNumbersForTrig.size(); ++j) {
254  if ((Frame == FrameNumbersForTrig.at(j)) &&
255  (fabs(TimeSlice - TimeSlicesForTrig.at(j) - fTriggerDelay) < fCoincThreshold)) {
256 
257  const raw::OpDetWaveform& wf = OpDetWaveformHandle->at(i);
258 
259  //fPulseRecoMgr.RecoPulse(wf);
261 
262  size_t NPulses = fThreshAlg.GetNPulse();
263 
264  fOffset = TimeSlice - TimeSlicesForTrig.at(j);
265  //fPedMean = fThreshAlg.PedMean();
266  //fPedRMS = fThreshAlg.PedRms();
267 
268  for (size_t k = 0; k != NPulses; ++k) {
270 
278 
279  fPulseTree->Fill();
280 
281  fAreas[fChannel].push_back(fArea);
282  }
283  else if (fMakeNonCoincTree) {
289 
290  fPulseTreeNonCoinc->Fill();
291  }
292  }
293  }
294  }
295  }
296  }
297  }
298 
299  //---------------------------------
300  uint32_t LEDCalibrationAna::ShaperToChannel(uint32_t Shaper)
301  {
302  static std::map<uint32_t, uint32_t> ShaperToChannelMap;
303  if (ShaperToChannelMap.size() == 0) {
304 
305  // temporary
306  for (size_t i = 0; i != 40; ++i) {
307  ShaperToChannelMap[i] = i;
308  }
309  }
310 
311  return ShaperToChannelMap[Shaper];
312  }
313 
314 } // namespace opdet
315 
316 namespace opdet {
318 }
pmtana::AlgoThreshold fThreshAlg
Utilities related to art service access.
EDAnalyzer(fhicl::ParameterSet const &pset)
Definition: EDAnalyzer.cc:6
void AddRecoAlgo(pmtana::PMTPulseRecoBase *algo, PMTPedestalBase *ped_algo=nullptr)
A method to set pulse reconstruction algorithm.
pure virtual base interface for detector clocks
void analyze(const art::Event &)
size_t GetNPulse() const
A getter for the number of reconstructed pulses from the input waveform.
pmtana::PulseRecoManager fPulseRecoMgr
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:65
bool Reconstruct(const pmtana::Waveform_t &) const
Implementation of ana_base::analyze method.
T get(std::string const &key) const
Definition: ParameterSet.h:314
EventNumber_t event() const
Definition: Event.cc:41
bool getByLabel(std::string const &label, std::string const &instance, Handle< PROD > &result) const
Class definition file of AlgoThreshold.
void SetDefaultPedAlgo(pmtana::PMTPedestalBase *algo)
A method to set a choice of pedestal estimation method.
std::map< uint32_t, std::vector< double > > fAreas
Class def header for a class ElecClock.
Class definition file of PMTPulseRecoBase.
Class definition file of PedAlgoEdges.
TCEvent evt
Definition: DataStructs.cxx:8
uint32_t ShaperToChannel(uint32_t Shaper)
LEDCalibrationAna(const fhicl::ParameterSet &)
RunNumber_t run() const
Definition: Event.cc:29
const pulse_param & GetPulse(size_t index=0) const
Class definition file of PulseRecoManager.