Skip to content

Commit f5d8576

Browse files
authored
Merge pull request #9 from hyperk/merge_waveform_simulation
Implement waveform simulation and hit finding algorithm for mPMT
2 parents 78a6ec5 + 5367d24 commit f5d8576

22 files changed

+13532
-102
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@ appWCTESingleEvent
77
appIWCDSingleEvent
88
appGenPileUpSpill
99

10-
# root file
10+
# output files
1111
*.root
12+
*.pdf
13+
1214

1315
.idea
1416
build-*

README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,25 @@ Input variables are:
5353
- `IDNuIntRate`,`BeamBkgRate`: Mean number of ID and background events per spill. In each spill, the actual number of interactions are drawn from a Poisson distribution, and interaction timing according to the bunch structure (see `BeamTiming` class under `app/utilities/WCRootData/`)
5454
- `UseOD`: Process OD hits
5555
- `NumOfSpillsSavedPerFile`, `TotalNumOfSpills`: output spill setup
56+
57+
## How to simulate and access digitized pulses
58+
Turn on waveform simulation in the parameter file by `< DigitizerType_PMTType = 1 >`.
59+
60+
For each true hit, a digitized waveform is simulated by sampling the single PE pulse (defined by the `< WaveformFile >` parameter) every 8 ns with 0.1 resolution. If there is another PE arriving within the hit integration window, the waveforms are added.
61+
62+
To do pulse fitting, the hit finding algorithm [here](https://github.com/hyperk/MDT/issues/8) is implemented to calculate the digitized time and charge.
63+
64+
Optionally, the waveform and digi TQ pulls of the first pulse of each PMT in each event can be saved by setting `< SaveWaveform = 1 >`. To read the pulses,
65+
```
66+
// open the file and get the digitzed waveform tree
67+
TTree* wcsimDigiWFTree = (TTree*)f->Get("wcsimDigiWFTree");
68+
TClonesArray *arr = new TClonesArray("TH1F");
69+
wcsimDigiWFTree->GetBranch("wcsimrootevent_waveform")->SetAutoDelete(kFALSE);
70+
wcsimDigiWFTree->SetBranchAddress("wcsimrootevent_waveform",&arr);
71+
// In each event, each array index corresponds to PMTId-1 (from 0 to nPMTs-1)
72+
wcsimDigiWFTree->GetEntry(0); // EvtId
73+
TH1F* h = (TH1F*)arr->At(0); // PMTId-1
74+
// Time and charge pulls of digitized hits
75+
TTree* WCSimDigiPulls = (TTree*)f->Get("WCSimDigiPulls");
76+
WCSimDigiPulls->Scan("PullT:TrueT:PullQ:TrueQ:EvtId:PMTId","PullT>-99"); // Pull==-99 means no digi hit for this PMT in this event
77+
```

app/application/PMTResponse3inchR12199_02.cc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ void PMTResponse3inchR12199_02::Initialize(int seed, const string &pmtname)
3030
s["TimingResMinimum"] = "TimingResMinimum";
3131
s["ScalFactorTTS"] = "ScalFactorTTS";
3232
s["SPECDFFile"] = "SPECDFFile";
33+
s["PMTDE"] = "PMTDE";
34+
s["PMTTime"] = "PMTTime";
3335
if( fPMTType!="" )
3436
{
3537
map<string, string>::iterator i;
@@ -43,7 +45,11 @@ void PMTResponse3inchR12199_02::Initialize(int seed, const string &pmtname)
4345
Conf->GetValue<float>(s["TimingResMinimum"], fTResMinimum);
4446
Conf->GetValue<float>(s["ScalFactorTTS"], fSclFacTTS);
4547
Conf->GetValue<string>(s["SPECDFFile"], fTxtFileSPECDF);
48+
Conf->GetValue<string>(s["PMTDE"], fPMTDEFile);
49+
Conf->GetValue<string>(s["PMTTime"], fPMTTFile);
4650
this->LoadCDFOfSPE(fTxtFileSPECDF);
51+
this->LoadPMTDE(fPMTDEFile);
52+
this->LoadPMTTime(fPMTTFile);
4753
}
4854

4955
float PMTResponse3inchR12199_02::HitTimeSmearing(float Q)
@@ -53,3 +59,6 @@ float PMTResponse3inchR12199_02::HitTimeSmearing(float Q)
5359
if( timingResolution<fTResMinimum ){ timingResolution = fTResMinimum; }
5460
return fRand->Gaus(0.0,timingResolution);
5561
}
62+
63+
///////////////////////////////////////////////////////////////////
64+
///////////////////////////////////////////////////////////////////

app/application/appWCTESingleEvent.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ int main(int argc, char **argv)
4848
MDT->RegisterPMTType(fPMTType[0], new Response3inchR14374_WCTE());
4949

5050
const vector<string> listWCRootEvt{"wcsimrootevent"};
51+
const vector<string> listWCRootCopyTree{"wcsimGeoT","Settings","wcsimRootOptionsT"};
5152

5253
// WCRootData is an interface class between MDT and WCSim root file
5354
WCRootData *inData = new WCRootData();
@@ -85,6 +86,7 @@ int main(int argc, char **argv)
8586
MDT->DoInitialize();
8687
}
8788
outData->WriteTree();
89+
for (auto s : listWCRootCopyTree) outData->CopyTree(fInFileName.c_str(),s.c_str());
8890
inData->CloseFile();
8991
}
9092

app/utilities/WCRootData/include/WCRootData.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,21 @@ class WCRootData
6969
float fHitTimeOffset;
7070
bool fMultDigiHits;
7171

72+
TTree *fWCSimDigiWFT;
73+
std::vector<TClonesArray*> fDigiWF;
74+
// TClonesArray* fDigiWF;
75+
// TClonesArray* fDigiWF2;
76+
// TClonesArray* fDigiWFOD;
77+
bool fSaveWF;
78+
79+
TTree *fWCSimDigiPulls;
80+
float fPullQ;
81+
float fPullT;
82+
float fTrueQ;
83+
float fTrueT;
84+
int fEvtId;
85+
int fPMTId;
86+
7287
private:
7388
void SetTubes(HitTubeCollection*, const int);
7489
TString fOutFileName;

app/utilities/WCRootData/src/WCRootData.cc

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,33 @@ WCRootData::WCRootData()
1515

1616
int mult_flag = 1;
1717
fHitTimeOffset = 0.;
18+
int save_wf = 0;
1819

1920
Configuration *Conf = Configuration::GetInstance();
2021
Conf->GetValue<float>("TimeOffset", fHitTimeOffset);
2122
Conf->GetValue<int>("FlagMultDigits", mult_flag);
23+
Conf->GetValue<int>("SaveWaveform", save_wf);
2224

2325
fMultDigiHits = bool(mult_flag);
26+
fSaveWF = bool(save_wf);
27+
28+
fWCSimDigiWFT = 0;
29+
fWCSimDigiPulls = 0;
30+
fPullQ = -99.;
31+
fPullT = -99.;
32+
fTrueQ = -99.;
33+
fTrueT = -99.;
34+
fEvtId = -99;
35+
fPMTId = -99;
2436
}
2537

2638
WCRootData::~WCRootData()
2739
{
2840
if( fWCGeom ){ delete fWCGeom; fWCGeom = 0; }
2941
if( fWCSimT ){ delete fWCSimT; fWCSimT = 0; }
3042
if( fWCSimC ){ delete fWCSimC; fWCSimC = 0; }
43+
if( fWCSimDigiWFT ){ delete fWCSimDigiWFT; fWCSimDigiWFT = 0; }
44+
if( fWCSimDigiPulls ){ delete fWCSimDigiPulls; fWCSimDigiPulls = 0; }
3145
fSpEvt.clear();
3246
fSpEvt.shrink_to_fit();
3347
isOD.clear();
@@ -92,7 +106,7 @@ void WCRootData::AddTrueHitsToMDT(HitTubeCollection *hc, PMTResponse *pr, float
92106
th->SetStartTime(aHitTime->GetPhotonStartTime()+intTime);
93107
for(int k=0; k<3; k++){ th->SetStartPosition(k, aHitTime->GetPhotonStartPos(k)); }
94108
th->SetCreatorProcess((int)(aHitTime->GetPhotonCreatorProcess()));
95-
if( !pr->ApplyDE(th) ){ continue; }
109+
if( !pr->ApplyDE(th,&(*hc)[tubeID]) ){ continue; }
96110

97111
(&(*hc)[tubeID])->AddRawPE(th);
98112
}
@@ -186,7 +200,28 @@ void WCRootData::CreateTree(const char *filename, const vector<string> &list)
186200
fWCSimT->Branch(list[i].c_str(), bAddress, &fSpEvt[i], bufferSize, 2);
187201
if ( list[i].find("OD")!=std::string::npos ) isOD[i] = true;
188202
}
203+
204+
if (fSaveWF)
205+
{
206+
fWCSimDigiWFT = new TTree("wcsimDigiWFTree","Digitized waveform for each PMT");
207+
fDigiWF.clear();
208+
fDigiWF = vector<TClonesArray*>(list.size(), 0);
209+
for(unsigned int i=0; i<list.size(); i++)
210+
{
211+
fDigiWF[i] = new TClonesArray("TH1F");
212+
fWCSimDigiWFT->Branch(Form("%s_waveform",list[i].c_str()),&fDigiWF[i]);
213+
}
214+
215+
fWCSimDigiPulls = new TTree("WCSimDigiPulls","Time and charge pulls of digitized hits");
216+
fWCSimDigiPulls->Branch("PullQ",&fPullQ);
217+
fWCSimDigiPulls->Branch("PullT",&fPullT);
218+
fWCSimDigiPulls->Branch("TrueQ",&fTrueQ);
219+
fWCSimDigiPulls->Branch("TrueT",&fTrueT);
220+
fWCSimDigiPulls->Branch("EvtId",&fEvtId);
221+
fWCSimDigiPulls->Branch("PMTId",&fPMTId);
222+
}
189223
}
224+
190225
}
191226

192227
void WCRootData::AddDigiHits(MDTManager *mdt, int eventID, int iPMT)
@@ -333,6 +368,41 @@ void WCRootData::AddDigiHits(HitTubeCollection *hc, TriggerInfo *ti, int eventID
333368
WCSimRootEventHeader *eh = anEvent->GetHeader();
334369
eh->SetDate( int(triggerTime) );
335370
}
371+
372+
if (fSaveWF)
373+
{
374+
TClonesArray &fDigiWFarray = *(fDigiWF[iPMT]);
375+
for(hc->Begin(); !hc->IsEnd(); hc->Next())
376+
{
377+
HitTube *aPH = &(*hc)();
378+
379+
// if (aPH->GetDigiWF())
380+
// new(fDigiWFarray[aPH->GetTubeID()-1]) TH1F(*(aPH->GetDigiWF()));
381+
// else new(fDigiWFarray[aPH->GetTubeID()-1]) TH1F();
382+
TH1F* h = (TH1F*)fDigiWFarray.ConstructedAt(aPH->GetTubeID()-1);
383+
if (aPH->GetDigiWF())
384+
{
385+
int nbins = aPH->GetDigiWF()->GetNbinsX();
386+
h->SetBins(nbins,aPH->GetDigiWF()->GetBinLowEdge(1),aPH->GetDigiWF()->GetBinLowEdge(nbins+1));
387+
for (int i=1;i<=nbins;i++) h->SetBinContent(i,aPH->GetDigiWF()->GetBinContent(i));
388+
}
389+
else
390+
{
391+
h->Reset();
392+
}
393+
394+
395+
fPullQ = aPH->GetPullQ();
396+
fPullT = aPH->GetPullT();
397+
fTrueQ = aPH->GetTrueQ();
398+
fTrueT = aPH->GetTrueT();
399+
fEvtId = eventID;
400+
fPMTId = aPH->GetTubeID();
401+
fWCSimDigiPulls->Fill();
402+
403+
aPH = NULL;
404+
} // PMT loop
405+
}
336406
}
337407

338408
void WCRootData::FillTree()
@@ -345,6 +415,14 @@ void WCRootData::FillTree()
345415
{
346416
fSpEvt[i]->ReInitialize();
347417
}
418+
if (fSaveWF)
419+
{
420+
fWCSimDigiWFT->Fill();
421+
for(unsigned int i=0; i<fDigiWF.size(); i++)
422+
{
423+
fDigiWF[i]->Clear();
424+
}
425+
}
348426
}
349427

350428

@@ -415,6 +493,11 @@ void WCRootData::WriteTree()
415493
TFile *f = fWCSimT->GetCurrentFile();
416494
f->cd();
417495
fWCSimT->Write();
496+
if (fSaveWF)
497+
{
498+
fWCSimDigiWFT->Write();
499+
fWCSimDigiPulls->Write();
500+
}
418501
f->Close();
419502
}
420503

cpp/include/HitDigitizer.h

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#include "PMTResponse.h"
77
#include "MTRandom.h"
88

9+
#include "TH1F.h"
10+
911
using std::cout;
1012
using std::endl;
1113
using std::vector;
@@ -15,13 +17,13 @@ class HitDigitizer
1517
public:
1618
HitDigitizer(int s=67823);
1719
virtual ~HitDigitizer();
18-
void Digitize(HitTubeCollection*, PMTResponse*);
19-
void DigitizeTube(HitTube*, PMTResponse*);
20+
virtual void Digitize(HitTubeCollection*, PMTResponse*);
21+
virtual void DigitizeTube(HitTube*, PMTResponse*);
2022

21-
void ApplyThreshold(double&, bool&);
22-
double DoTruncate(const double, const double);
23+
virtual void ApplyThreshold(double&, bool&);
24+
virtual double DoTruncate(const double, const double);
2325

24-
private:
26+
protected:
2527
float fPrecisionCharge;
2628
float fPrecisionTiming;
2729
float fEfficiency;
@@ -30,3 +32,31 @@ class HitDigitizer
3032

3133
MTRandom *fRand;
3234
};
35+
36+
// mPMT specific digitizer
37+
class HitDigitizer_mPMT : public HitDigitizer
38+
{
39+
public:
40+
HitDigitizer_mPMT(int s=67823);
41+
virtual ~HitDigitizer_mPMT();
42+
void LoadWaveform(const string &filename);
43+
void DigitizeTube(HitTube*, PMTResponse*);
44+
void ApplyThreshold(double&, bool&);
45+
TH1F BuildWavetrain(const vector<TrueHit*> PEs, double waveform_window);
46+
void FitWavetrain(TH1F hist, vector<double>& vDigiT, vector<double>& vDigiQ);
47+
48+
private:
49+
TH1F* hWF;
50+
float fAmplitudeSigma;
51+
float fDt;
52+
float fDv;
53+
float fWaveformOffset;
54+
float fADCToPE;
55+
int fIntegralPreceding;
56+
int fIntegralFollowing;
57+
int fChargeWindowBefore;
58+
int fChargeWindowAfter;
59+
float fDigiTimeOffset;
60+
int fHitInsensitivityPeriod;
61+
float fAmplitudeThreshold;
62+
};

cpp/include/HitTube.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include "TrueHit.h"
2323
using std::vector;
2424

25+
#include "TH1F.h"
26+
2527
class HitTube
2628
{
2729
public:
@@ -74,6 +76,22 @@ class HitTube
7476
float GetChargeDigi(const int i) const { return fChargeDigi[i]; }
7577
const vector<int>& GetParentCompositionDigi(const int i) const { return fParentCompDigi[i]; }
7678

79+
void SetDigiWF(const TH1F& hist)
80+
{
81+
if(hDigiWF != nullptr) delete hDigiWF;
82+
hDigiWF = new TH1F(hist);
83+
hDigiWF->SetDirectory(0);
84+
}
85+
TH1F* GetDigiWF()
86+
{
87+
return hDigiWF;
88+
}
89+
void SetDigiPulls(float pullT, float pullQ) { fPullT = pullT; fPullQ = pullQ;}
90+
void SetTrueTQ(float trueT, float trueQ) { fTrueT = trueT; fTrueQ = trueQ;}
91+
float GetPullT() {return fPullT;}
92+
float GetPullQ() {return fPullQ;}
93+
float GetTrueT() {return fTrueT;}
94+
float GetTrueQ() {return fTrueQ;}
7795

7896
private:
7997
int fNRawPE;
@@ -88,4 +106,10 @@ class HitTube
88106
vector<float> fTimeDigi;
89107
vector<float> fChargeDigi;
90108
vector<vector<int>> fParentCompDigi;
109+
110+
TH1F* hDigiWF;
111+
float fPullT;
112+
float fPullQ;
113+
float fTrueT;
114+
float fTrueQ;
91115
};

cpp/include/MDTManager.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ class MDTManager
3737
PMTResponse* GetPMTResponse(const string &s="Def") { return fPMTResp[s]; }
3838

3939
private:
40-
// TriggerAlgo *fTrigAlgo;
41-
HitDigitizer *fDgtzr;
40+
map<string, HitDigitizer*> fDgtzr;
4241
MTRandom *fRndm;
4342

4443
map<string, TriggerAlgo*> fTrigAlgo;

cpp/include/PMTResponse.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class PMTResponse
1818
virtual ~PMTResponse() {};
1919
virtual double GetRawSPE(const TrueHit* th=NULL, const HitTube* ht=NULL) = 0;
2020
virtual float HitTimeSmearing(float) = 0;
21+
virtual float HitTimeSmearing(float,int) = 0;
2122
virtual void Initialize(int, const string &s="") = 0;
2223
virtual bool ApplyDE(const TrueHit* th=NULL, const HitTube* ht=NULL) = 0;
2324

@@ -38,12 +39,21 @@ class GenericPMTResponse : public PMTResponse
3839
void Initialize(int, const string &s="");
3940
virtual double GetRawSPE(const TrueHit* th=NULL, const HitTube* ht=NULL);
4041
virtual float HitTimeSmearing(float);
42+
virtual float HitTimeSmearing(float,int);
4143
virtual bool ApplyDE(const TrueHit* th=NULL, const HitTube* ht=NULL);
4244

4345
protected:
4446
void LoadCDFOfSPE(const string &s);
4547
float fqpe0[501];
4648
string fTxtFileSPECDF;
49+
void LoadPMTDE(const string &s);
50+
int fLoadDE;
51+
std::vector<double> fDE;
52+
string fPMTDEFile;
53+
void LoadPMTTime(const string &s);
54+
int fLoadT;
55+
std::vector<double> fT;
56+
string fPMTTFile;
4757

4858
//private:
4959
protected:

0 commit comments

Comments
 (0)