From 14caa016e52b78f391f0d6c50a6299d9d8c86867 Mon Sep 17 00:00:00 2001 From: Ryan Ambrose <george.ryan.ambrose@gmail.com> Date: Wed, 4 Apr 2018 15:15:51 -0600 Subject: [PATCH] Generalized calibration to first determine appropriate timing cuts (hence new "preprocess" files), removing the need of arbitrary hard-coded timing values. --- CALIBRATION/shms_hgcer_calib/calibration.C | 94 ++++++---- CALIBRATION/shms_hgcer_calib/calibration.h | 16 +- CALIBRATION/shms_hgcer_calib/efficiencies.C | 10 +- CALIBRATION/shms_hgcer_calib/preprocess.C | 191 ++++++++++++++++++++ CALIBRATION/shms_hgcer_calib/preprocess.h | 99 ++++++++++ CALIBRATION/shms_hgcer_calib/run_cal.C | 36 +++- 6 files changed, 401 insertions(+), 45 deletions(-) create mode 100644 CALIBRATION/shms_hgcer_calib/preprocess.C create mode 100644 CALIBRATION/shms_hgcer_calib/preprocess.h diff --git a/CALIBRATION/shms_hgcer_calib/calibration.C b/CALIBRATION/shms_hgcer_calib/calibration.C index 3c7c23e0..a627ceec 100644 --- a/CALIBRATION/shms_hgcer_calib/calibration.C +++ b/CALIBRATION/shms_hgcer_calib/calibration.C @@ -49,8 +49,9 @@ void calibration::Begin(TTree * /*tree*/) printf("\n\n"); TString option = GetOption(); + TString report_option = option(0,option.Length()-79); Info("Begin", "Script will fail unless 'calibration.C+' is used"); - Info("Begin", "Starting calibration process with option: %s", option.Data()); + Info("Begin", "Starting calibration process with option: %s", report_option.Data()); Info("Begin", "To load all branches, use option readall (warning, very slow)"); Info("Begin", "To see details of calibration, use option showall"); Info("Begin", "Default calibration is the HGC, for NGC use option NGC"); @@ -65,7 +66,7 @@ void calibration::Begin(TTree * /*tree*/) if (option.Contains("showall")) fFullShow = kTRUE; if (option.Contains("trackfired")) fTrack = kTRUE; if (option.Contains("pions") || option.Contains("pion")) fPions = kTRUE; - if (option.Contains("cut") || fPions || option.Contains("cuts")) fCut = kTRUE; + if (option.Contains("cut") || fPions || option.Contains("cuts")) fCut = kTRUE; } void calibration::SlaveBegin(TTree * /*tree*/) @@ -76,7 +77,25 @@ void calibration::SlaveBegin(TTree * /*tree*/) printf("\n\n"); TString option = GetOption(); - + + TString timing_mean_1 = option(option.Length()-79,option.Length()-69); + TString timing_std_1 = option(option.Length()-67,option.Length()-60); + TString timing_mean_2 = option(option.Length()-59,option.Length()-49); + TString timing_std_2 = option(option.Length()-47,option.Length()-40); + TString timing_mean_3 = option(option.Length()-39,option.Length()-29); + TString timing_std_3 = option(option.Length()-27,option.Length()-20); + TString timing_mean_4 = option(option.Length()-19,option.Length()-9); + TString timing_std_4 = option(option.Length()-7,option.Length()-0); + + timing_mean[0] = timing_mean_1.Atof(); + timing_std[0] = timing_std_1.Atof(); + timing_mean[1] = timing_mean_2.Atof(); + timing_std[1] = timing_std_2.Atof(); + timing_mean[2] = timing_mean_3.Atof(); + timing_std[2] = timing_std_3.Atof(); + timing_mean[3] = timing_mean_4.Atof(); + timing_std[3] = timing_std_4.Atof(); + //Check option if (option.Contains("readall")) fFullRead = kTRUE; if (option.Contains("NGC")) fNGC = kTRUE; @@ -100,8 +119,8 @@ void calibration::SlaveBegin(TTree * /*tree*/) if (fNGC) //Set up histograms for NGC { ADC_min = -10; - ADC_max = 250; - bins = 2*(abs(ADC_min) + abs(ADC_max)); + ADC_max = 200; + bins = 12*(abs(ADC_min) + abs(ADC_max)); } if (!fNGC) //Set up histograms for HGC @@ -148,7 +167,7 @@ void calibration::SlaveBegin(TTree * /*tree*/) GetOutputList()->Add(fCut_electron); fCut_pion = new TH2F("Cut_pion", "Visualization of pion cut; Calorimeter Energy (GeV); Pre-Shower Energy (GeV)", 250, 0, 1.0, 250, 0, 1.0); GetOutputList()->Add(fCut_pion); - + printf("\n\n"); } @@ -172,10 +191,17 @@ Bool_t calibration::Process(Long64_t entry) // // The return value is currently not used. - //Output to verify script is working, and store the total number of events if (entry % 100000 == 0) printf("Processing Entry number %lld\n",entry); + if (entry == 1) + { + cout << timing_mean[0] << " " << timing_std[0] << endl; + cout << timing_mean[1] << " " << timing_std[1] << endl; + cout << timing_mean[2] << " " << timing_std[2] << endl; + cout << timing_mean[3] << " " << timing_std[3] << endl; + } + //Define quantities to loop over Int_t fpmts; fpmts = fNGC ? fngc_pmts : fhgc_pmts; //Note HGC & NGC have the same # of PMTS @@ -183,7 +209,7 @@ Bool_t calibration::Process(Long64_t entry) //Get the entry to loop over if (fFullRead) fChain->GetTree()->GetEntry(entry); else b_Ndata_P_tr_p->GetEntry(entry); - + //Require only one good track reconstruction for the event if (Ndata_P_tr_p != 1) return kTRUE; @@ -200,11 +226,10 @@ Bool_t calibration::Process(Long64_t entry) for (Int_t ipmt = 0; ipmt < fpmts; ipmt++) { //Perform a loose timing cut - if (!fFullRead) fNGC ? b_P_ngcer_goodAdcPulseTime->GetEntry(entry) : b_P_hgcer_goodAdcTdcDiffTime->GetEntry(entry); - fTiming_Full->Fill(fNGC ? P_ngcer_goodAdcPulseTime[ipmt] : P_hgcer_goodAdcTdcDiffTime[ipmt]); - if (fNGC ? P_ngcer_goodAdcPulseTime[ipmt] < 50 || P_ngcer_goodAdcPulseTime[ipmt] > 125 : - P_hgcer_goodAdcTdcDiffTime[ipmt] > -17.0 || P_hgcer_goodAdcTdcDiffTime[ipmt] < -30.0) continue; - fTiming_Cut->Fill(fNGC ? P_ngcer_goodAdcPulseTime[ipmt] : P_hgcer_goodAdcTdcDiffTime[ipmt]); + if (!fFullRead) fNGC ? b_P_ngcer_goodAdcTdcDiffTime->GetEntry(entry) : b_P_hgcer_goodAdcTdcDiffTime->GetEntry(entry); + fTiming_Full->Fill(fNGC ? P_ngcer_goodAdcTdcDiffTime[ipmt] : P_hgcer_goodAdcTdcDiffTime[ipmt]); + if (fNGC ? P_ngcer_goodAdcTdcDiffTime[ipmt] > -10.0 || P_ngcer_goodAdcTdcDiffTime[ipmt] < -35.0 : TMath::Abs(P_hgcer_goodAdcTdcDiffTime[ipmt] - timing_mean[ipmt]) > 3*timing_std[ipmt]) continue; + fTiming_Cut->Fill(fNGC ? P_ngcer_goodAdcTdcDiffTime[ipmt] : P_hgcer_goodAdcTdcDiffTime[ipmt]); //Cuts to remove entries corresponding to a PMT not registering a hit if (!fFullRead) fNGC ? b_P_ngcer_goodAdcPulseInt->GetEntry(entry) : b_P_hgcer_goodAdcPulseInt->GetEntry(entry); @@ -491,17 +516,17 @@ void calibration::Terminate() } //Rebin the histograms, add functionality to bin HGC & NGC independently - //Not needed since unit conversion into SI, but available in the future - /* - for (Int_t ipmt=0; ipmt < (fNGC ? fngc_pmts : fhgc_pmts); ipmt++) - { - for (Int_t iquad=0; iquad<4; iquad++) - { - fNGC ? PulseInt_quad[iquad][ipmt]->Rebin(20) : PulseInt_quad[iquad][ipmt]->Rebin(20); - } - fNGC ? PulseInt[ipmt]->Rebin(20) : PulseInt[ipmt]->Rebin(20); - } -*/ + if (fTrack) { + for (Int_t ipmt=0; ipmt < (fNGC ? fngc_pmts : fhgc_pmts); ipmt++) + { + for (Int_t iquad=0; iquad<4; iquad++) + { + fNGC ? PulseInt_quad[iquad][ipmt]->Rebin(4) : PulseInt_quad[iquad][ipmt]->Rebin(4); + } + fNGC ? PulseInt[ipmt]->Rebin(4) : PulseInt[ipmt]->Rebin(4); + } + } + //Canvases to display cut information if (fFullShow) { @@ -598,7 +623,7 @@ void calibration::Terminate() if (fFullShow) quad_cuts_ipmt->cd(ipad); //Perform search for the SPE and save the peak into the array xpeaks - fFullShow ? s->Search(PulseInt_quad[iquad][ipmt], 2.0, "nobackground", 0.001) : s->Search(PulseInt_quad[iquad][ipmt], 2.5, "nobackground&&nodraw", 0.001); + fFullShow ? s->Search(PulseInt_quad[iquad][ipmt], 2.5, "nobackground", 0.001) : s->Search(PulseInt_quad[iquad][ipmt], 2.5, "nobackground&&nodraw", 0.001); TList *functions = PulseInt_quad[iquad][ipmt]->GetListOfFunctions(); TPolyMarker *pm = (TPolyMarker*)functions->FindObject("TPolyMarker"); Double_t *xpeaks = pm->GetX(); @@ -811,25 +836,24 @@ void calibration::Terminate() //Perform search for the SPE and save the peak into the array xpeaks if (fFullShow) quad_cuts_ipmt->cd(iquad+1); - //fNGC ? PulseInt_quad[iquad][ipmt]->GetXaxis()->SetRangeUser(150,2000) : PulseInt_quad[ipmt][ipmt]->GetXaxis()->SetRangeUser(5,20); - fFullShow ? s->Search(PulseInt_quad[iquad][ipmt], 2.0, "nobackground", 0.001) : s->Search(PulseInt_quad[iquad][ipmt], 2.0, "nobackground&&nodraw", 0.001); + fNGC ? PulseInt_quad[iquad][ipmt]->GetXaxis()->SetRangeUser(0,30) : PulseInt_quad[ipmt][ipmt]->GetXaxis()->SetRangeUser(0,30); + fFullShow ? s->Search(PulseInt_quad[iquad][ipmt], 1.0, "nobackground", 0.001) : s->Search(PulseInt_quad[iquad][ipmt], 1.5, "nobackground&&nodraw", 0.001); TList *functions = PulseInt_quad[iquad][ipmt]->GetListOfFunctions(); TPolyMarker *pm = (TPolyMarker*)functions->FindObject("TPolyMarker"); Double_t *xpeaks = pm->GetX(); + PulseInt_quad[iquad][ipmt]->GetXaxis()->SetRangeUser(-1,200); //Use the peak to fit the SPE with a Gaussian to determine the mean - Gauss1->SetRange(xpeaks[1]-3, xpeaks[1]+3); - Gauss1->SetParameter(1, xpeaks[1]); + Gauss1->SetRange(xpeaks[0]-3, xpeaks[0]+3); + Gauss1->SetParameter(1, xpeaks[0]); Gauss1->SetParameter(2, 10.); Gauss1->SetParLimits(0, 0., 2000.); - Gauss1->SetParLimits(1, xpeaks[1]-3, xpeaks[1]+3); + Gauss1->SetParLimits(1, xpeaks[0]-3, xpeaks[0]+3); Gauss1->SetParLimits(2, 0.5, 10.); - //PulseInt_quad[iquad][ipmt]->GetXaxis()->SetRangeUser(5,20); fFullShow ? PulseInt_quad[iquad][ipmt]->Fit("Gauss1","RQ") : PulseInt_quad[iquad][ipmt]->Fit("Gauss1","RQN"); //Store the mean of the SPE in the mean array provided it is not zero, passes a loose statistical cut, and is above a minimum channel number - //Added condition that iquad != ipmt since spectrum is quite different - if (xpeaks[1] != 0.0 && PulseInt_quad[iquad][ipmt]->GetBinContent(PulseInt_quad[iquad][ipmt]->GetXaxis()->FindBin(xpeaks[1])) > 50 && iquad != ipmt) mean[iquad] = Gauss1->GetParameter(1); + if (xpeaks[0] != 0.0 && PulseInt_quad[iquad][ipmt]->GetBinContent(PulseInt_quad[iquad][ipmt]->GetXaxis()->FindBin(xpeaks[0])) > 10 && ipmt != iquad) mean[iquad] = Gauss1->GetParameter(1); } Double_t xscale = 0.0; @@ -866,7 +890,7 @@ void calibration::Terminate() if (fFullShow) final_spectra_ipmt->cd(1); //Find the location of the SPE and subtract from 1.0 to determine accuracy of calibration - Gauss1->SetRange(0.50, 2.0); + Gauss1->SetRange(0.50, 1.50); Gauss1->SetParameter(0, 0.05); Gauss1->SetParameter(1, 1.0); Gauss1->SetParameter(2, 0.3); @@ -898,7 +922,7 @@ void calibration::Terminate() if (fFullShow) final_spectra_mk2_ipmt->cd(1); //Find the location of the SPE and subtract from 1.0 to determine accuracy of calibration - Gauss1->SetRange(0.50,2.0); + Gauss1->SetRange(0.50, 1.50); Gauss1->SetParameter(0, 0.05); Gauss1->SetParameter(1, 1.0); Gauss1->SetParameter(2, 0.3); diff --git a/CALIBRATION/shms_hgcer_calib/calibration.h b/CALIBRATION/shms_hgcer_calib/calibration.h index f73c1ef2..2ae4093c 100644 --- a/CALIBRATION/shms_hgcer_calib/calibration.h +++ b/CALIBRATION/shms_hgcer_calib/calibration.h @@ -14,6 +14,7 @@ #include <TSelector.h> #include <TH1.h> #include <TH2.h> +#include <TNtuple.h> const Int_t fhgc_pmts = 4; const Int_t fngc_pmts = 4; @@ -67,8 +68,11 @@ public : TCanvas *final_spectra_combined; TCanvas *final_spectra_combined_mk2; TCanvas *scaled_poisson; - TCanvas *scaled_total; - + TCanvas *scaled_total; + + // Declaration of preprocessing quantities + Double_t timing_mean[4]; + Double_t timing_std[4]; // Declaration of leaf types Int_t Ndata_P_aero_goodNegAdcPed; @@ -623,6 +627,8 @@ public : Double_t P_ngcer_goodAdcPulseIntRaw[4]; //[Ndata.P.ngcer.goodAdcPulseIntRaw] Int_t Ndata_P_ngcer_goodAdcPulseTime; Double_t P_ngcer_goodAdcPulseTime[4]; //[Ndata.P.ngcer.goodAdcPulseTime] + Int_t Ndata_P_ngcer_goodAdcTdcDiffTime; + Double_t P_ngcer_goodAdcTdcDiffTime[4]; Int_t Ndata_P_ngcer_npe; Double_t P_ngcer_npe[4]; //[Ndata.P.ngcer.npe] Int_t Ndata_P_ngcer_numGoodAdcHits; @@ -1452,6 +1458,8 @@ public : TBranch *b_P_ngcer_goodAdcPulseIntRaw; //! TBranch *b_Ndata_P_ngcer_goodAdcPulseTime; //! TBranch *b_P_ngcer_goodAdcPulseTime; //! + TBranch *b_Ndata_P_ngcer_goodAdcTdcDiffTime; + TBranch *b_P_ngcer_goodAdcTdcDiffTime; TBranch *b_Ndata_P_ngcer_npe; //! TBranch *b_P_ngcer_npe; //! TBranch *b_Ndata_P_ngcer_numGoodAdcHits; //! @@ -1727,7 +1735,7 @@ public : TBranch *b_Event_Branch_fEvtHdr_fTargetPol; //! TBranch *b_Event_Branch_fEvtHdr_fRun; //! - calibration(TTree * /*tree*/ =0) : fChain(0) {fPulseInt = 0, fPulseInt_quad = 0, fCut_everything = 0, fCut_electron = 0, fCut_pion = 0, fBeta_Cut = 0, fBeta_Full = 0, fTiming_Cut = 0, fTiming_Full = 0, fFullRead = kFALSE, fFullShow = kFALSE, fNGC = kFALSE, fTrack = kFALSE, fCut = kFALSE, fPions = kFALSE;} + calibration(TTree * /*tree*/ =0) : fChain(0) {fPulseInt = 0, fPulseInt_quad = 0, fCut_everything = 0, fCut_electron = 0, fCut_pion = 0, fBeta_Cut = 0, fBeta_Full = 0, fTiming_Cut = 0, fTiming_Full = 0, fFullRead = kFALSE, fFullShow = kFALSE, fNGC = kFALSE, fTrack = kFALSE, fCut = kFALSE, fPions = kFALSE, timing_mean[0] = 0, timing_mean[1] = 0, timing_mean[2] = 0, timing_mean[3] = 0, timing_std[0] = 0, timing_std[1] = 0, timing_std[2] = 0, timing_std[3] = 0;} virtual ~calibration() { } virtual Int_t Version() const { return 2; } virtual void Begin(TTree *tree); @@ -2316,6 +2324,8 @@ void calibration::Init(TTree *tree) fChain->SetBranchAddress("P.ngcer.goodAdcPulseIntRaw", P_ngcer_goodAdcPulseIntRaw, &b_P_ngcer_goodAdcPulseIntRaw); fChain->SetBranchAddress("Ndata.P.ngcer.goodAdcPulseTime", &Ndata_P_ngcer_goodAdcPulseTime, &b_Ndata_P_ngcer_goodAdcPulseTime); fChain->SetBranchAddress("P.ngcer.goodAdcPulseTime", P_ngcer_goodAdcPulseTime, &b_P_ngcer_goodAdcPulseTime); + fChain->SetBranchAddress("Ndata.P.ngcer.goodAdcTdcDiffTime", &Ndata_P_ngcer_goodAdcTdcDiffTime, &b_Ndata_P_ngcer_goodAdcTdcDiffTime); + fChain->SetBranchAddress("P.ngcer.goodAdcTdcDiffTime", P_ngcer_goodAdcTdcDiffTime, &b_P_ngcer_goodAdcTdcDiffTime); fChain->SetBranchAddress("Ndata.P.ngcer.npe", &Ndata_P_ngcer_npe, &b_Ndata_P_ngcer_npe); fChain->SetBranchAddress("P.ngcer.npe", P_ngcer_npe, &b_P_ngcer_npe); fChain->SetBranchAddress("Ndata.P.ngcer.numGoodAdcHits", &Ndata_P_ngcer_numGoodAdcHits, &b_Ndata_P_ngcer_numGoodAdcHits); diff --git a/CALIBRATION/shms_hgcer_calib/efficiencies.C b/CALIBRATION/shms_hgcer_calib/efficiencies.C index 3d299a0e..543909e8 100644 --- a/CALIBRATION/shms_hgcer_calib/efficiencies.C +++ b/CALIBRATION/shms_hgcer_calib/efficiencies.C @@ -262,8 +262,8 @@ Bool_t efficiencies::Process(Long64_t entry) Float_t esemimajor_axis = 0.28; Float_t esemiminor_axis = 0.04;*/ Float_t eangle = 3.0*3.14159/4.0; - Float_t ex_center = 0.375; - Float_t ey_center = 0.360; + Float_t ex_center = 0.490; + Float_t ey_center = 0.400; Float_t esemimajor_axis = 0.38; Float_t esemiminor_axis = 0.05; if (pow((P_cal_fly_earray/p - ex_center)*cos(eangle) + (P_cal_pr_eplane/p - ey_center)*sin(eangle),2)/pow(esemimajor_axis,2) + @@ -290,9 +290,9 @@ Bool_t efficiencies::Process(Long64_t entry) Float_t piy_center = 0.03; Float_t pisemimajor_axis = 0.1; Float_t pisemiminor_axis = 0.02;*/ - Float_t pix_center = 0.00; - Float_t piy_center = 0.00; - Float_t pisemimajor_axis = 0.01; + Float_t pix_center = 0.30; + Float_t piy_center = 0.05; + Float_t pisemimajor_axis = 0.08; Float_t pisemiminor_axis = 0.02; if (pow((P_cal_fly_earray/p - pix_center)*cos(piangle) + (P_cal_pr_eplane/p - piy_center)*sin(piangle),2)/pow(pisemimajor_axis,2) + pow((P_cal_fly_earray/p - pix_center)*sin(piangle) - (P_cal_pr_eplane/p - piy_center)*cos(piangle),2)/pow(pisemiminor_axis,2) < 1) diff --git a/CALIBRATION/shms_hgcer_calib/preprocess.C b/CALIBRATION/shms_hgcer_calib/preprocess.C new file mode 100644 index 00000000..a6bbff4d --- /dev/null +++ b/CALIBRATION/shms_hgcer_calib/preprocess.C @@ -0,0 +1,191 @@ +#define preprocess_cxx +// The class definition in preprocess.h has been generated automatically +// by the ROOT utility TTree::MakeSelector(). This class is derived +// from the ROOT class TSelector. For more information on the TSelector +// framework see $ROOTSYS/README/README.SELECTOR or the ROOT User Manual. + + +// The following methods are defined in this file: +// Begin(): called every time a loop on the tree starts, +// a convenient place to create your histograms. +// SlaveBegin(): called after Begin(), when on PROOF called only on the +// slave servers. +// Process(): called for each event, in this function you decide what +// to read and fill your histograms. +// SlaveTerminate: called at the end of the loop on the tree, when on PROOF +// called only on the slave servers. +// Terminate(): called at the end of the loop on the tree, +// a convenient place to draw/fit your histograms. +// +// To use this file, try the following session on your Tree T: +// +// root> T->Process("preprocess.C") +// root> T->Process("preprocess.C","some options") +// root> T->Process("preprocess.C+") +// + + +#include "preprocess.h" +#include <TH1.h> +#include <TF1.h> +#include <TCanvas.h> +#include <TSpectrum.h> +#include <TPolyMarker.h> +#include <TStyle.h> +#include <TNtuple.h> + +void preprocess::Begin(TTree * /*tree*/) +{ + // The Begin() function is called at the start of the query. + // When running with PROOF Begin() is only called on the client. + // The tree argument is deprecated (on PROOF 0 is passed). + + printf("\n\n"); + + Info("Begin", "Starting preprocessing script to: determine correct fADC timing cuts"); + + printf("\n"); + TString option = GetOption(); + if (option.Contains("NGC")) fNGC = kTRUE; + if (option.Contains("showall")) fFullShow = kTRUE; +} + +void preprocess::SlaveBegin(TTree * /*tree*/) +{ + // The SlaveBegin() function is called after the Begin() function. + // When running with PROOF SlaveBegin() is called on each slave server. + // The tree argument is deprecated (on PROOF 0 is passed). + + TString option = GetOption(); + + fTiming = new TH1F*[4]; + for (Int_t ipmt = 0; ipmt < 4; ipmt++) + { + fTiming[ipmt] = new TH1F(Form("Timing_PMT%d",ipmt+1),Form("ADC TDC Diff Time PMT%d; Time (ns); Counts",ipmt+1), 400, -50, 0); + GetOutputList()->Add(fTiming[ipmt]); + } + +} + +Bool_t preprocess::Process(Long64_t entry) +{ + // The Process() function is called for each entry in the tree (or possibly + // keyed object in the case of PROOF) to be processed. The entry argument + // specifies which entry in the currently loaded tree is to be processed. + // When processing keyed objects with PROOF, the object is already loaded + // and is available via the fObject pointer. + // + // This function should contain the \"body\" of the analysis. It can contain + // simple or elaborate selection criteria, run algorithms on the data + // of the event and typically fill histograms. + // + // The processing can be stopped by calling Abort(). + // + // Use fStatus to set the return value of TTree::Process(). + // + // The return value is currently not used. + + fReader.SetEntry(entry); + + //Output to verify script is working, and store the total number of events + if (entry % 100000 == 0) printf("Processing Entry number %lld\n",entry); + + //Require only one good track reconstruction for the event + if (Ndata_P_tr_p[0] != 1) return kTRUE; + + //Redundant, but useful if multiple tracks will be allowed + for (Int_t itrack = 0; itrack < Ndata_P_tr_p[0]; itrack++) + { + //Require cut on particle velocity + if (TMath::Abs(P_tr_beta[itrack] -1.0) > 0.2) return kTRUE; + + //Fill the histograms + for (Int_t ipmt = 0; ipmt < 4; ipmt++) + { + fTiming[ipmt]->Fill(P_hgcer_goodAdcTdcDiffTime[ipmt]); + } + } + + return kTRUE; +} + +void preprocess::SlaveTerminate() +{ + // The SlaveTerminate() function is called after all entries or objects + // have been processed. When running with PROOF SlaveTerminate() is called + // on each slave server. + +} + +void preprocess::Terminate() +{ + // The Terminate() function is the last function to be called during + // a query. It always runs on the client, it can be used to present + // the results graphically or save the results to file. + printf("\n\n"); + Info("Terminate", "calibrating '%s'", (fNGC ? "NGC" : "HGC")); + Info("Terminate", "'%s' showing", (fFullShow ? "full" : "minimal")); + Info("Terminate","Histograms formed, now determining timing peaks"); + + //Create temporary file to store fit information + TFile ofile("Timing_Cuts.root","RECREATE"); + + //Create arrays to store Gaussian fit information + Float_t mean[4]; + Float_t sigma[4]; + + //Create Ntuple to store timing data + TNtuple timing_data("timing_data","Storage of Timing Information","Mean:Std"); + + //Single Gaussian to find mean and spread of peak + TF1 *Gauss1 = new TF1("Gauss1",pregauss,-10,200,3); + Gauss1->SetParNames("Amplitude","Mean","Std. Dev."); + + //Have to extract histograms from OutputList + TH1F *Timing[4]; + for (Int_t ipmt = 0; ipmt < 4; ipmt++) + { + Timing[ipmt] = dynamic_cast<TH1F*> (GetOutputList()->FindObject(Form("Timing_PMT%d",ipmt+1))); + } + + //Visualize the timing information + if (fFullShow) + { + cTiming = new TCanvas("Timing", "Timing Information"); + cTiming->Divide(2,2); + } + + TSpectrum *s = new TSpectrum(2); + + //Main loop to find timing peaks + for (Int_t ipmt = 0; ipmt < 4; ipmt++) + { + //Use peak finding algorithm from TSpectrum + + if (fFullShow) cTiming->cd(ipmt+1); + + //Perform search for largest peak and save into array xpeaks + fFullShow ? s->Search(Timing[ipmt],2.0,"nobackground",0.9) : s->Search(Timing[ipmt],2.0,"nobackground&&nodraw",0.9); + TList *functions = Timing[ipmt]->GetListOfFunctions(); + TPolyMarker *pm = (TPolyMarker*)functions->FindObject("TPolyMarker"); + Double_t *xpeaks = pm->GetX(); + + //Use the peak to fit with a Gaussian to determine range of cut + Gauss1->SetRange(xpeaks[0]-3, xpeaks[0]+3); + Gauss1->SetParameter(0, 10000.); + Gauss1->SetParameter(1, xpeaks[0]); + Gauss1->SetParameter(2, 0.4); + //Gauss1->SetParLimits(0, 0., 10000.); + Gauss1->SetParLimits(1, xpeaks[0]-3, xpeaks[0]+3); + Gauss1->SetParLimits(2, 0.2, 1.); + fFullShow ? Timing[ipmt]->Fit("Gauss1","RQ") : Timing[ipmt]->Fit("Gauss1","RQN"); + mean[ipmt] = Gauss1->GetParameter(1); + sigma[ipmt] = Gauss1->GetParameter(2); + timing_data.Fill(mean[ipmt],sigma[ipmt]); + } + + cout << "\nTiming cut results are (mean & sigma):\n" << Form("PMT 1: %f, %f\nPMT 2: %f, %f\nPMT 3: %f, %f\nPMT 4: %f, %f\n\n",mean[0],sigma[0],mean[1],sigma[1],mean[2],sigma[2],mean[3],sigma[3]); + + timing_data.Write(); + ofile.Close(); +} diff --git a/CALIBRATION/shms_hgcer_calib/preprocess.h b/CALIBRATION/shms_hgcer_calib/preprocess.h new file mode 100644 index 00000000..db4376a0 --- /dev/null +++ b/CALIBRATION/shms_hgcer_calib/preprocess.h @@ -0,0 +1,99 @@ +////////////////////////////////////////////////////////// +// This class has been automatically generated on +// Fri Mar 2 15:04:26 2018 by ROOT version 6.10/02 +// from TTree T/Hall A Analyzer Output DST +// found on file: /home/rambrose/hallc_replay/ROOTfiles/shms_replay_production_all_2732_-1.root +////////////////////////////////////////////////////////// + +#ifndef preprocess_h +#define preprocess_h + +#include <TROOT.h> +#include <TChain.h> +#include <TFile.h> +#include <TSelector.h> +#include <TTreeReader.h> +#include <TTreeReaderValue.h> +#include <TTreeReaderArray.h> + +// Headers needed by this particular selector + + +class preprocess : public TSelector { +public : + TTreeReader fReader; //!the tree reader + TTree *fChain = 0; //!pointer to the analyzed TTree or TChain + + Bool_t fNGC; + Bool_t fFullShow; + + // Declaration of Histograms + TH1F **fTiming; + + // Declaration of Canvases + TCanvas *cTiming; + + // Readers to access the data (delete the ones you do not need). + TTreeReaderArray<Double_t> P_hgcer_goodAdcTdcDiffTime = {fReader, "P.hgcer.goodAdcTdcDiffTime"}; + TTreeReaderArray<Int_t> Ndata_P_tr_p = {fReader, "Ndata.P.tr.p"}; + TTreeReaderArray<Double_t> P_tr_beta = {fReader, "P.tr.beta"}; + + + preprocess(TTree * /*tree*/ =0) {fNGC = kFALSE, fFullShow = kFALSE; } + virtual ~preprocess() { } + virtual Int_t Version() const { return 2; } + virtual void Begin(TTree *tree); + virtual void SlaveBegin(TTree *tree); + virtual void Init(TTree *tree); + virtual Bool_t Notify(); + virtual Bool_t Process(Long64_t entry); + virtual Int_t GetEntry(Long64_t entry, Int_t getall = 0) { return fChain ? fChain->GetTree()->GetEntry(entry, getall) : 0; } + virtual void SetOption(const char *option) { fOption = option; } + virtual void SetObject(TObject *obj) { fObject = obj; } + virtual void SetInputList(TList *input) { fInput = input; } + virtual TList *GetOutputList() const { return fOutput; } + virtual void SlaveTerminate(); + virtual void Terminate(); + + ClassDef(preprocess,0); + +}; + +#endif + +#ifdef preprocess_cxx +void preprocess::Init(TTree *tree) +{ + // The Init() function is called when the selector needs to initialize + // a new tree or chain. Typically here the reader is initialized. + // It is normally not necessary to make changes to the generated + // code, but the routine can be extended by the user if needed. + // Init() will be called many times when running on PROOF + // (once per file to be processed). + + fReader.SetTree(tree); +} + +Bool_t preprocess::Notify() +{ + // The Notify() function is called when a new file is opened. This + // can be either for a new TTree in a TChain or when when a new TTree + // is started when using PROOF. It is normally not necessary to make changes + // to the generated code, but the routine can be extended by the + // user if needed. The return value is currently not used. + + return kTRUE; +} + +//Gaussian distribution is used to find the mean of the SPE and determine spacing between subsequent NPE +Double_t pregauss(Double_t *x, Double_t *par) +{ + Double_t result1 = par[0]*exp((-0.5)*(pow((x[0] - par[1]),2)/pow((par[2]),2))); + Double_t result2 = par[3]*exp((-0.5)*(pow((x[0] - par[4]),2)/pow((par[5]),2))); + Double_t result3 = par[6]*exp((-0.5)*(pow((x[0] - par[7]),2)/pow((par[8]),2))); + Double_t result4 = par[9]*exp((-0.5)*(pow((x[0] - par[10]),2)/pow((par[11]),2))); + Double_t result5 = par[12]*exp((-0.5)*(pow((x[0] - par[13]),2)/pow((par[14]),2))); + return result1 + result2 + result3 + result4 + result5; +} + +#endif // #ifdef preprocess_cxx diff --git a/CALIBRATION/shms_hgcer_calib/run_cal.C b/CALIBRATION/shms_hgcer_calib/run_cal.C index e3d32b47..868a8ca6 100644 --- a/CALIBRATION/shms_hgcer_calib/run_cal.C +++ b/CALIBRATION/shms_hgcer_calib/run_cal.C @@ -4,7 +4,7 @@ #include <string> #include <stdio.h> -void run_cal(Int_t RunNumber = 0, Int_t NumEvents = 0) +void run_cal(Int_t RunNumber = 0, Int_t NumEvents = 0, Int_t coin = 0) { if (RunNumber == 0) { @@ -17,6 +17,11 @@ void run_cal(Int_t RunNumber = 0, Int_t NumEvents = 0) cout << "\nNumber of Events to analyze: "; cin >> NumEvents; } + if (coin == 0) + { + cout << "\nIf this is a coincident run enter 1: "; + cin >> coin; + } cin.ignore(numeric_limits<streamsize>::max(), '\n'); @@ -30,14 +35,41 @@ void run_cal(Int_t RunNumber = 0, Int_t NumEvents = 0) getline(std::cin, eff_raw); TString eff_option = eff_raw; + cout << "\n\n"; + TChain ch("T"); - ch.Add(Form("../../ROOTfiles/shms_replay_production_%d_%d.root", RunNumber, NumEvents)); + if (coin == 1) ch.Add(Form("../../ROOTfiles/coin_replay_production_%d_%d.root", RunNumber, NumEvents)); + else ch.Add(Form("../../ROOTfiles/shms_replay_production_all_%d_%d.root", RunNumber, NumEvents)); TProof *proof = TProof::Open(""); proof->SetProgressDialog(0); ch.SetProof(); if (calib_option != "NA") { + //Perform a "preprocess" of replay to extact timing information + ch.Process("preprocess.C+",calib_option); + if (calib_option.Contains("showall")) + { + TString preprocessing_input; + cout << "\n\nPlease verify if timing cuts are correct (y/n): "; + cin >> preprocessing_input; + if (preprocessing_input != "y") return; + } + + //Obtain cut information from preprocessing + TFile preprocess_file("Timing_Cuts.root"); + TNtuple *input_data = new TNtuple("input_data","Storage for Client Timing Information","Mean:Std"); + preprocess_file.GetObject("timing_data",input_data); + float *timing_row_content; + for (Int_t irow = 0; irow < input_data->GetEntries(); irow++) + { + input_data->GetEntry(irow); + timing_row_content = input_data->GetArgs(); + calib_option.Append(Form(" %f %f",timing_row_content[0],timing_row_content[1])); + } + preprocess_file.Close(); + + //Start calibration process ch.Process("calibration.C+",calib_option); cout << "\n\nUpdate calibration constants with the better estimate (y/n)? "; -- GitLab