1010#include " canvas/Utilities/InputTag.h"
1111
1212#include " Offline/RecoDataProducts/inc/CaloDigi.hh"
13-
14- #include < iomanip>
15- #include < sstream>
16- #include < vector>
17-
18- #include < TDirectory.h>
19- #include < TFile.h>
20- #include < TGraph.h>
21- #include < TGraphErrors.h>
22- #include < TH1F.h>
23- #include < TH2F.h>
24- #include < TMath.h>
25- #include < iostream>
26- #include " TH1.h"
27- #include " TH2.h"
2813#include " art_root_io/TFileService.h"
2914
30- #include < TCanvas.h>
31- #include < TF1.h>
32- #include < TLine.h>
33- #include < TProfile.h>
34- #include < TSpline.h>
35- #include < TTree.h>
36- #include < TVirtualFitter.h>
3715#include < algorithm>
3816#include < cmath>
3917#include < fstream>
40- #include < iomanip> // Libreria per manipolare il formato di output
18+ #include < iomanip>
4119#include < iostream>
4220#include < map>
21+ #include < sstream>
22+ #include < vector>
23+
24+ #include " TCanvas.h"
25+ #include " TDirectory.h"
26+ #include " TF1.h"
27+ #include " TFile.h"
28+ #include " TFitResult.h"
29+ #include " TGraph.h"
30+ #include " TGraphErrors.h"
31+ #include " TH1.h"
32+ #include " TH1F.h"
33+ #include " TH2.h"
34+ #include " TH2F.h"
35+ #include " TKey.h"
36+ #include " TLine.h"
37+ #include " TMath.h"
38+ #include " TProfile.h"
39+ #include " TSpline.h"
40+ #include " TTree.h"
41+ #include " TVirtualFitter.h"
4342
4443namespace mu2e {
4544class CaloiercAnalyzer : public art ::EDAnalyzer {
@@ -63,35 +62,45 @@ class CaloiercAnalyzer : public art::EDAnalyzer {
6362 false };
6463 fhicl::Atom<int > skipAfterN{
6564 fhicl::Name (" skipAfterN" ), fhicl::Comment (" Don't fit after N hits" ), -1 };
65+ fhicl::Atom<bool > produceTree{fhicl::Name (" produceTree" ),
66+ fhicl::Comment (" Produce tree with fit results" ),
67+ true };
6668 };
6769
6870 explicit CaloiercAnalyzer (const art::EDAnalyzer::Table<Config>& config);
6971 void analyze (art::Event const & event) override ;
7072 void endJob () override ;
7173
7274 private:
75+ int load_templates ();
76+ TFitResultPtr fit_waveform (TGraph* graph, int sipm_id);
77+
7378 std::string caloDigiModuleLabel_;
7479 std::string caloDigiInstanceLabel_;
7580 int verbosity_;
7681 std::string splineFilename_;
7782 bool uset0_;
7883 int skipAfterN_;
84+ bool produceTree_;
7985
80- std::map<int , std::vector<int >> digiMap;
81- std::map<int , std::vector<float >> timeMap;
82- std::map<int , std::vector<float >> chi2Map;
83- std::map<int , std::vector<float >> chi2rMap;
86+ std::map<int , std::vector<int >> digiMap;
87+ std::map<int , std::vector<float >> timeMap;
88+ std::map<int , std::vector<float >> chi2Map;
89+ std::map<int , std::vector<float >> chi2rMap;
90+ std::map<int , std::map<int , TSpline3*>> templateMap;
8491
8592 int total_events;
8693 int last_event;
8794 int total_hits;
8895 int total_unsorted;
8996 int total_badfits;
9097
98+ // Fit parameters
99+ const static int FITSCALE = 3850 .;
100+ const static int FITOFF = 0 .;
101+ const static int FITPED = 0 .;
102+
91103 art::ServiceHandle<art::TFileService> tfs;
92- art::TFileDirectory* sameChanDir;
93- art::TFileDirectory* sameBoardDir;
94- art::TFileDirectory* diffBoardDir;
95104
96105 std::map<int , TH1F*> map_h1_dt_singlechan;
97106 std::map<int , TGraph*> map_g_dtevt_singlechan;
@@ -102,8 +111,11 @@ class CaloiercAnalyzer : public art::EDAnalyzer {
102111 std::map<int , TH1F*> map_h1_dt_diffboard;
103112 std::map<int , TGraph*> map_g_dtevt_diffboard;
104113
105- TSpline3* spline;
106- TF1* f_spline;
114+ TTree* tree;
115+ long int t_ewt;
116+ std::vector<int >* t_SiPMID = 0 ;
117+ std::vector<std::vector<float >>* t_times = 0 ;
118+ std::vector<std::vector<float >>* t_chi2ndf = 0 ;
107119};
108120} // namespace mu2e
109121
@@ -114,44 +126,112 @@ mu2e::CaloiercAnalyzer::CaloiercAnalyzer(const art::EDAnalyzer::Table<Config>& c
114126 , verbosity_(config().verbosity())
115127 , splineFilename_(config().splineFilename())
116128 , uset0_(config().uset0())
117- , skipAfterN_(config().skipAfterN()) {
118- TFile* filetemp = TFile::Open (splineFilename_.c_str ());
119- if (!filetemp->IsOpen ()) {
120- std::cout << splineFilename_ << " NOT FOUND" << std::endl;
121- }
122-
123- char hname[200 ];
124- sprintf (hname, " spline_0_1" );
125- if (filetemp->Get (hname))
126- spline = (TSpline3*)filetemp->Get (hname);
127- else {
128- std::cout << " No template.." << std::endl;
129- }
130-
131- f_spline = new TF1 (
132- " f_spline" ,
133- [this ](double * x, double * par) {
134- return par[0 ] * this ->spline ->Eval (x[0 ] - par[1 ]) + par[2 ];
135- },
136- 0 .,
137- 19 .,
138- 3 );
139- f_spline->SetParNames (" scale" , " tpeak" , " ped" );
140- f_spline->SetNpx (10000 );
141- f_spline->SetRange (spline->GetXmin (), spline->GetXmax ());
129+ , skipAfterN_(config().skipAfterN())
130+ , produceTree_(config().produceTree()) {
131+ load_templates ();
142132
143133 total_events = 0 ;
144134 total_hits = 0 ;
145135 total_unsorted = 0 ;
146136 total_badfits = 0 ;
147137 // TVirtualFitter::SetDefaultFitter("Minuit");
148138
149- art::TFileDirectory t_sameChanDir = tfs->mkdir (" sameChannel" );
150- art::TFileDirectory t_sameBoardDir = tfs->mkdir (" sameBoard" );
151- art::TFileDirectory t_diffBoardDir = tfs->mkdir (" diffBoard" );
152- sameChanDir = &t_sameChanDir;
153- sameBoardDir = &t_sameBoardDir;
154- diffBoardDir = &t_diffBoardDir;
139+ if (produceTree_) {
140+ tree = tfs->make <TTree>(" tree" , " Event tree with timing fit results" );
141+ tree->Branch (" ewt" , &t_ewt, " t_ewt/L" );
142+ tree->Branch (" SiPMID" , &t_SiPMID);
143+ tree->Branch (" times" , &t_times);
144+ tree->Branch (" chi2ndf" , &t_chi2ndf);
145+ }
146+ }
147+
148+ int mu2e::CaloiercAnalyzer::load_templates () {
149+ TFile template_file (splineFilename_.c_str (), " READ" );
150+ if (!template_file.IsOpen ()) {
151+ std::cout << splineFilename_ << " NOT FOUND" << std::endl;
152+ return 1 ;
153+ } else {
154+ std::cout << " LOADING SPLINES FROM " << splineFilename_ << std::endl;
155+ }
156+
157+ TIter nextkey (template_file.GetListOfKeys ());
158+ while (auto key = (TKey*)nextkey ()) {
159+ std::string templateName = key->GetName ();
160+ int board, channel;
161+ if (sscanf (templateName.c_str (), " spline_%d_%d" , &board, &channel) == 2 ) {
162+ // HARDCODED HACK TO MATCH FILE NAMES
163+ if (board == 2 ) {
164+ board = 1 ;
165+ } else if (board == 1 ) {
166+ board = 2 ;
167+ }
168+ //
169+
170+ templateMap[board][channel] =
171+ (TSpline3*)template_file.Get (templateName.c_str ());
172+ std::cout << " Loaded template for Board " << board << " channel " << channel
173+ << " \n " ;
174+ }
175+ }
176+
177+ return 0 ;
178+ }
179+
180+ TFitResultPtr mu2e::CaloiercAnalyzer::fit_waveform (TGraph* graph, int sipm_id) {
181+ int board = (sipm_id / 20 ) % 6 ;
182+ int channel = sipm_id % 20 ;
183+ TSpline3* thisSpline;
184+ if (templateMap.find (board) == templateMap.end ()) {
185+ // No templates for this board! Using the first available...
186+ if (!templateMap.empty ()) {
187+ auto board_pair = templateMap.begin ();
188+ auto channel_pair = board_pair->second .begin ();
189+ std::cout << " No available template for Board " << board << " channel "
190+ << channel << " !\n " ;
191+ std::cout << " Using the one of Board " << board_pair->first << " channel "
192+ << channel_pair->first << " instead!\n " ;
193+ thisSpline = channel_pair->second ;
194+ } else {
195+ std::cout << " No templates? Skipping fit...\n " ;
196+ return -1 ;
197+ }
198+ } else if (templateMap[board].find (channel) == templateMap[board].end ()) {
199+ // No template for this channel -- but board is known
200+ if (!templateMap[board].empty ()) {
201+ auto channel_pair = templateMap[board].begin ();
202+ std::cout << " No available template for Board " << board << " channel "
203+ << channel << " !\n " ;
204+ std::cout << " Using the one of Board " << board << " channel "
205+ << channel_pair->first << " instead!\n " ;
206+ thisSpline = channel_pair->second ;
207+ } else {
208+ std::cout << " No templates for board " << board << " ?? Skipping fit...\n " ;
209+ return -1 ;
210+ }
211+ } else { // all good!
212+ thisSpline = templateMap[board][channel];
213+ }
214+
215+ double xmin = thisSpline->GetXmin ();
216+ double xmax = thisSpline->GetXmax ();
217+ TF1* f_spline = new TF1 (
218+ " f_spline" ,
219+ [&](double * x, double * par) {
220+ return par[0 ] * thisSpline->Eval (x[0 ] - par[1 ]) + par[2 ];
221+ },
222+ 0 .,
223+ 19 .,
224+ 3 );
225+ f_spline->SetParNames (" scale" , " tpeak offset" , " ped offset" , " roc" , " chan" );
226+ f_spline->SetNpx (10000 );
227+ f_spline->SetRange (xmin, xmax);
228+ f_spline->SetParameter (0 , FITSCALE);
229+ f_spline->SetParameter (1 , FITOFF);
230+ f_spline->SetParameter (2 , FITPED);
231+ TFitResultPtr fitResult = graph->Fit (f_spline, " QRNS" );
232+ delete f_spline;
233+
234+ return fitResult;
155235}
156236
157237void mu2e::CaloiercAnalyzer::analyze (art::Event const & event) {
@@ -163,6 +243,11 @@ void mu2e::CaloiercAnalyzer::analyze(art::Event const& event) {
163243 const auto & caloDigis =
164244 *event.getValidHandle (consumes<mu2e::CaloDigiCollection>(caloDigiModuleLabel_));
165245
246+ if (caloDigis.size () == 0 ) {
247+ // std::cout << "No calodigis!\n";
248+ return ;
249+ }
250+
166251 // Fill time-ordered map for each sipm
167252 digiMap.clear ();
168253 for (uint ihit = 0 ; ihit < caloDigis.size (); ihit++) {
@@ -235,26 +320,21 @@ void mu2e::CaloiercAnalyzer::analyze(art::Event const& event) {
235320 gadc->SetPoint (gi, gi, this_waveform[gi]);
236321 // gadc->SetPointError(gi, 0., 1.);
237322 }
238- // std::cout<<" ("<<this_waveform.size()<<" points)\n";
239- f_spline->SetParameters (3850 , 0 , 0 );
240- // double xmin, xmax;
241- // f_spline->GetRange(xmin, xmax);
242- // std::cout<<"Now fitting in range ("<<xmin<<","<<xmax<<")\n";
243- int fitStatus = gadc->Fit (" f_spline" , " QRN" ); // FIT!
244- if (fitStatus >= 0 ) {
245- // std::cout<<"fitStatus: "<<fitStatus<<", ped:
246- // "<<f_spline->GetParameter(2)<<", time:
247- // "<<f_spline->GetParameter(1)<<", scale:
248- // "<<f_spline->GetParameter(0)<<"\n"; std::cout<<"chi2:
249- // "<<f_spline->GetChisquare()<<", ndf: "<<f_spline->GetNDF()<<",
250- // chi2/ndf: "<<f_spline->GetChisquare()/f_spline->GetNDF()<<"\n";
323+ TFitResultPtr fitResult =
324+ fit_waveform (gadc, caloDigis[idx].SiPMID ()); // FIT!
325+ if (fitResult >= 0 ) {
326+ // std::cout<<"fitResult: "<<fitResult<<", ped:
327+ // "<<fitResult->Parameter(2)<<", time:
328+ // "<<fitResult->Parameter(1)<<", scale:
329+ // "<<fitResult->Parameter(0)<<"\n"; std::cout<<"chi2:
330+ // "<<fitResult->Chi2()<<", ndf: "<<fitResult->Ndf()<<",
331+ // chi2/ndf: "<<fitResult->Chi2()/fitResult->Ndf()<<"\n";
251332 timeMap[pair.first ].push_back (
252- 5 . * (caloDigis[idx].t0 () + f_spline->GetParameter (1 )));
253- chi2Map[pair.first ].push_back (f_spline->GetChisquare ());
254- chi2rMap[pair.first ].push_back (f_spline->GetChisquare () /
255- f_spline->GetNDF ());
333+ 5 . * (caloDigis[idx].t0 () + fitResult->Parameter (1 )));
334+ chi2Map[pair.first ].push_back (fitResult->Chi2 ());
335+ chi2rMap[pair.first ].push_back (fitResult->Chi2 () / fitResult->Ndf ());
256336 } else { // if bad fit, don't fill at all
257- std::cout << " Bad fit status: " << fitStatus << " for sipmid "
337+ std::cout << " Bad fit status: " << fitResult << " for sipmid "
258338 << pair.first << " hit " << idx << " \n " ;
259339 total_badfits++;
260340 }
@@ -285,6 +365,20 @@ void mu2e::CaloiercAnalyzer::analyze(art::Event const& event) {
285365 }
286366 }
287367
368+ // ------- Fill the tree
369+ if (produceTree_) {
370+ t_ewt = this_eventNumber;
371+ t_SiPMID->clear ();
372+ t_times->clear ();
373+ t_chi2ndf->clear ();
374+ for (auto pair : timeMap) {
375+ t_SiPMID->push_back (pair.first );
376+ t_times->push_back (pair.second );
377+ t_chi2ndf->push_back (chi2rMap[pair.first ]);
378+ }
379+ tree->Fill ();
380+ }
381+
288382 // --------Now we can fill hists
289383
290384 // Same channel
@@ -443,7 +537,7 @@ void mu2e::CaloiercAnalyzer::analyze(art::Event const& event) {
443537}
444538
445539void mu2e::CaloiercAnalyzer::endJob () {
446- std::cout << " \n -- JOB SUMMARY --\n " ;
540+ std::cout << " \n -- CaloiercAnalyzer JOB SUMMARY --\n " ;
447541 std::cout << " Total events: " << total_events << " (last event: " << last_event
448542 << " )\n " ;
449543 std::cout << " Total hits: " << total_hits << " \n " ;
0 commit comments