Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DDIRCLut.cc
Go to the documentation of this file.
1 // $Id$
2 //
3 // File: DDIRCLut.cc
4 //
5 
6 #include <cassert>
7 #include <math.h>
8 using namespace std;
9 
10 #include "DDIRCLut.h"
11 #include "DANA/DApplication.h"
12 #include <JANA/JCalibration.h>
13 
14 //---------------------------------
15 // DDIRCLut (Constructor)
16 //---------------------------------
18 {
19  DIRC_DEBUG_HISTS = false;
20  gPARMS->SetDefaultParameter("DIRC:DEBUG_HISTS",DIRC_DEBUG_HISTS);
21 
22  DIRC_TRUTH_BARHIT = false;
23  gPARMS->SetDefaultParameter("DIRC:TRUTH_BARHIT",DIRC_TRUTH_BARHIT);
24 
25  DIRC_TRUTH_PIXELTIME = false;
26  gPARMS->SetDefaultParameter("DIRC:TRUTH_PIXELTIME",DIRC_TRUTH_PIXELTIME);
27 
28  // timing cuts for photons
29  DIRC_CUT_TDIFFD = 2; // direct cut in ns
30  gPARMS->SetDefaultParameter("DIRC:CUT_TDIFFD",DIRC_CUT_TDIFFD);
31  DIRC_CUT_TDIFFR = 3; // reflected cut in ns
32  gPARMS->SetDefaultParameter("DIRC:CUT_TDIFFR",DIRC_CUT_TDIFFR);
33 
34  // Gives DeltaT = 0, but shouldn't it be v=20.3767 [cm/ns] for 1.47125
35  DIRC_LIGHT_V = 19.80; // v=19.8 [cm/ns] for 1.5141
36  gPARMS->SetDefaultParameter("DIRC:LIGHT_V",DIRC_LIGHT_V);
37 
38  // sigma (thetaC for single photon) in radiams
39  DIRC_SIGMA_THETAC = 0.0085;
40  gPARMS->SetDefaultParameter("DIRC:SIGMA_THETAC",DIRC_SIGMA_THETAC);
41 
42  // set PID for different passes in debuging histograms
43  dFinalStatePIDs.push_back(Positron);
44  dFinalStatePIDs.push_back(PiPlus);
45  dFinalStatePIDs.push_back(KPlus);
46  dFinalStatePIDs.push_back(Proton);
47 
48  dMaxChannels = 108*64;
49 
50  dCriticalAngle = asin(1.00028/1.47125); // n_quarzt = 1.47125; //(1.47125 <==> 390nm)
51  dIndex = 1.473;
52 
53  if(DIRC_DEBUG_HISTS)
54  CreateDebugHistograms();
55 }
56 
57 bool DDIRCLut::brun(JEventLoop *loop) {
58 
59  dapp = dynamic_cast<DApplication*>(loop->GetJApplication());
60  dDIRCLutReader = dapp->GetDIRCLut(loop->GetJEvent().GetRunNumber());
61 
62  // get DIRC geometry
63  vector<const DDIRCGeometry*> locDIRCGeometry;
64  loop->Get(locDIRCGeometry);
65  dDIRCGeometry = locDIRCGeometry[0];
66 
67  return true;
68 }
69 
71 
72  ////////////////////////////////////
73  // LUT histograms and diagnostics //
74  ////////////////////////////////////
75 
76  //dapp->RootWriteLock(); //ACQUIRE ROOT LOCK!!
77  {
78  //TDirectory *mainDir = gDirectory;
79  //TDirectory *dircDir = gDirectory->mkdir("DIRC_debug");
80  //dircDir->cd();
81 
82  hDiff = (TH1I*)gROOT->FindObject("hDiff");
83  hDiff_Pixel[0] = (TH2I*)gROOT->FindObject("hDiff_Pixel_N");
84  hDiff_Pixel[1] = (TH2I*)gROOT->FindObject("hDiff_Pixel_S");
85  hDiffT = (TH1I*)gROOT->FindObject("hDiffT");
86  hDiffD = (TH1I*)gROOT->FindObject("hDiffD");
87  hDiffR = (TH1I*)gROOT->FindObject("hDiffR");
88  hTime = (TH1I*)gROOT->FindObject("hTime");
89  hCalc = (TH1I*)gROOT->FindObject("hCalc");
90  hNph = (TH1I*)gROOT->FindObject("hNph");
91  if(!hDiff) hDiff = new TH1I("hDiff",";t_{calc}-t_{measured} [ns];entries [#]", 400,-20,20);
92  if(!hDiff_Pixel[0]) hDiff_Pixel[0] = new TH2I("hDiff_Pixel_N","; Channel ID; t_{calc}-t_{measured} [ns];entries [#]", dMaxChannels, 0, dMaxChannels, 400,-20,20);
93  if(!hDiff_Pixel[1]) hDiff_Pixel[1] = new TH2I("hDiff_Pixel_S","; Channel ID; t_{calc}-t_{measured} [ns];entries [#]", dMaxChannels, 0, dMaxChannels, 400,-20,20);
94  if(!hDiffT) hDiffT = new TH1I("hDiffT",";t_{calc}-t_{measured} [ns];entries [#]", 400,-20,20);
95  if(!hDiffD) hDiffD = new TH1I("hDiffD",";t_{calc}-t_{measured} [ns];entries [#]", 400,-20,20);
96  if(!hDiffR) hDiffR = new TH1I("hDiffR",";t_{calc}-t_{measured} [ns];entries [#]", 400,-20,20);
97  if(!hTime) hTime = new TH1I("hTime",";propagation time [ns];entries [#]", 1000,0,200);
98  if(!hCalc) hCalc = new TH1I("hCalc",";calculated time [ns];entries [#]", 1000,0,200);
99  if(!hNph) hNph = new TH1I("hNph",";detected photons [#];entries [#]", 150,0,150);
100 
101  // DeltaThetaC for each particle type (e, pi, K, p) and per pixel
102  for(uint loc_i=0; loc_i<dFinalStatePIDs.size(); loc_i++) {
103  Particle_t locPID = dFinalStatePIDs[loc_i];
104  string locParticleName = ParticleType(locPID);
105  string locParticleROOTName = ParticleName_ROOT(locPID);
106 
107  hDeltaThetaC[locPID] = (TH1I*)gROOT->FindObject(Form("hDeltaThetaC_%s",locParticleName.data()));
108  if(!hDeltaThetaC[locPID])
109  hDeltaThetaC[locPID] = new TH1I(Form("hDeltaThetaC_%s",locParticleName.data()), "cherenkov angle; #Delta#theta_{C} [rad]", 200,-0.5,0.5);
110  hDeltaThetaC_Pixel[locPID] = (TH2I*)gROOT->FindObject(Form("hDeltaThetaC_Pixel_%s",locParticleName.data()));
111  if(!hDeltaThetaC_Pixel[locPID])
112  hDeltaThetaC_Pixel[locPID] = new TH2I(Form("hDeltaThetaC_Pixel_%s",locParticleName.data()), "cherenkov angle; Pixel ID; #Delta#theta_{C} [rad]", 10000, 0, 10000, 200,-0.5,0.5);
113  }
114 
115  //mainDir->cd();
116  }
117  //dapp->RootUnLock(); //REMOVE ROOT LOCK!!
118 
119  return true;
120 }
121 
122 bool DDIRCLut::CalcLUT(TVector3 locProjPos, TVector3 locProjMom, const vector<const DDIRCPmtHit*> locDIRCHits, double locFlightTime, Particle_t locPID, shared_ptr<DDIRCMatchParams>& locDIRCMatchParams, const vector<const DDIRCTruthBarHit*> locDIRCBarHits, map<shared_ptr<const DDIRCMatchParams>, vector<const DDIRCPmtHit*> >& locDIRCTrackMatchParams) const
123 {
124  double locMass = ParticleMass(locPID);
125 
126  // get bar and track position/momentum from extrapolation
127  TVector3 momInBar = locProjMom;
128  TVector3 posInBar = locProjPos;
129 
130  ////////////////////////////////////////////
131  // option to cheat and use truth position //
132  ////////////////////////////////////////////
133  if(DIRC_TRUTH_BARHIT && locDIRCBarHits.size() > 0) {
134 
135  TVector3 bestMatchPos, bestMatchMom;
136  double bestFlightTime = 999.;
137  double bestMatchDist = 999.;
138  for(int i=0; i<(int)locDIRCBarHits.size(); i++) {
139  TVector3 locDIRCBarHitPos(locDIRCBarHits[i]->x, locDIRCBarHits[i]->y, locDIRCBarHits[i]->z);
140  TVector3 locDIRCBarHitMom(locDIRCBarHits[i]->px, locDIRCBarHits[i]->py, locDIRCBarHits[i]->pz);
141  if((posInBar - locDIRCBarHitPos).Mag() < bestMatchDist) {
142  bestMatchDist = (posInBar - locDIRCBarHitPos).Mag();
143  bestMatchPos = locDIRCBarHitPos;
144  bestMatchMom = locDIRCBarHitMom;
145  bestFlightTime = locDIRCBarHits[i]->t;
146  }
147  }
148 
149  momInBar = bestMatchMom;
150  posInBar = bestMatchPos;
151  locFlightTime = bestFlightTime;
152  }
153 
154  // clear object to store good photons
155  if(locDIRCMatchParams == nullptr)
156  locDIRCMatchParams = std::make_shared<DDIRCMatchParams>();
157 
158  // initialize variables for LUT summary
159  double locAngle = CalcAngle(momInBar, locMass);
160  map<Particle_t, double> locExpectedAngle = CalcExpectedAngles(momInBar);
161  map<Particle_t, double> logLikelihoodSum;
162  Particle_t locHypothesisPID = PiPlus;
163  for(uint loc_i = 0; loc_i<dFinalStatePIDs.size(); loc_i++) {
164  logLikelihoodSum[dFinalStatePIDs[loc_i]]=0;
165  if(fabs(ParticleMass(dFinalStatePIDs[loc_i])-ParticleMass(locPID)) < 0.01) locHypothesisPID = dFinalStatePIDs[loc_i];
166  }
167 
168  // loop over DIRC hits
169  int nPhotons = 0;
170  int nPhotonsThetaC = 0;
171  double meanThetaC = 0.;
172  double meanDeltaT = 0.;
173  for (unsigned int loc_i = 0; loc_i < locDIRCHits.size(); loc_i++){
174 
175  const DDIRCPmtHit* locDIRCHit = locDIRCHits[loc_i];
176  bool locIsGood = false;
177  CalcPhoton(locDIRCHit, locFlightTime, posInBar, momInBar, locExpectedAngle, locAngle, locHypothesisPID, logLikelihoodSum, nPhotonsThetaC, meanThetaC, meanDeltaT, locIsGood);
178  if(locIsGood) {
179  // count good photons and add hits to associated objects
180  nPhotons++;
181  locDIRCTrackMatchParams[locDIRCMatchParams].push_back(locDIRCHit);
182  }
183 
184  }// end loop over hits
185 
186  if(DIRC_DEBUG_HISTS) {
187  dapp->RootWriteLock();
188  hNph->Fill(nPhotons);
189  dapp->RootUnLock();
190  }
191 
192  // skip tracks without enough photons
193  if(nPhotons<5)
194  return false;
195 
196  // set DIRCMatchParameters contents
197  locDIRCMatchParams->dThetaC = meanThetaC/(double)nPhotonsThetaC;
198  locDIRCMatchParams->dDeltaT = meanDeltaT/(double)nPhotonsThetaC;
199  locDIRCMatchParams->dExpectedThetaC = locAngle;
200  locDIRCMatchParams->dLikelihoodElectron = logLikelihoodSum[Positron];
201  locDIRCMatchParams->dLikelihoodPion = logLikelihoodSum[PiPlus];
202  locDIRCMatchParams->dLikelihoodKaon = logLikelihoodSum[KPlus];
203  locDIRCMatchParams->dLikelihoodProton = logLikelihoodSum[Proton];
204  locDIRCMatchParams->dNPhotons = nPhotons;
205  locDIRCMatchParams->dExtrapolatedPos = posInBar;
206  locDIRCMatchParams->dExtrapolatedMom = momInBar;
207  locDIRCMatchParams->dExtrapolatedTime = locFlightTime;
208 
209  return true;
210 }
211 
212 vector<pair<double,double>> DDIRCLut::CalcPhoton(const DDIRCPmtHit *locDIRCHit, double locFlightTime, TVector3 posInBar, TVector3 momInBar, map<Particle_t, double> locExpectedAngle, double locAngle, Particle_t locPID, map<Particle_t, double> &logLikelihoodSum, int &nPhotonsThetaC, double &meanThetaC, double &meanDeltaT, bool &isGood) const
213 {
214  // initialize photon pairs for time and thetaC
215  pair<double, double> locDIRCPhoton(-999., -999.);
216  vector<pair<double, double>> locDIRCPhotons;
217 
218  TVector3 fnX1 = TVector3 (1,0,0);
219  TVector3 fnY1 = TVector3 (0,1,0);
220  TVector3 fnZ1 = TVector3 (0,0,1);
221 
222  double tangle,luttheta,evtime;
223  int64_t pathid;
224  TVector3 dir,dird;
225 
226  // get bar number from geometry
227  int bar = dDIRCGeometry->GetBar(posInBar.Y());
228  if(bar < 0 || bar > 47) return locDIRCPhotons;
229 
230  // get channel information for LUT
231  int channel = locDIRCHit->ch;
232 
233  // get box from bar number (North/Upper = 0 and South/Lower = 1)
234  int box = (bar < 24) ? 1 : 0;
235  if((box == 0 && channel < dMaxChannels) || (box == 1 && channel >= dMaxChannels))
236  return locDIRCPhotons;
237 
238  // use hit time to determine if reflected or not
239  double hitTime = locDIRCHit->t - locFlightTime;
240 
241  // option to use truth hit time rather than smeared hit time
242  vector<const DDIRCTruthPmtHit*> locTruthDIRCHits;
243  locDIRCHit->Get(locTruthDIRCHits);
244  if(DIRC_TRUTH_PIXELTIME && locTruthDIRCHits.size() > 0) {
245  double locTruthTime = locTruthDIRCHits[0]->t - locFlightTime;
246  hitTime = locTruthTime;
247  }
248 
249  // needs to be X dependent choice for reflection cut (from CCDB?)
250  bool reflected = hitTime>0; // try all photons as reflected for now
251 
252  // get position along bar for calculated time
253  double radiatorL = dDIRCGeometry->GetBarLength(bar);
254  double barend = dDIRCGeometry->GetBarEnd(bar);
255  double lenz = fabs(barend - posInBar.X());
256 
257  // get length for reflected and direct photons
258  double rlenz = 2*radiatorL - lenz; // reflected
259  double dlenz = lenz; // direct
260  if(reflected) lenz = 2*radiatorL - lenz;
261 
262  // check for pixel before going through loop
263  int box_channel = channel%dMaxChannels;
264  if(dDIRCLutReader->GetLutPixelAngleSize(bar, box_channel) == 0)
265  return locDIRCPhotons;
266 
267  // loop over LUT table for this bar/pixel to calculate thetaC
268  for(uint i = 0; i < dDIRCLutReader->GetLutPixelAngleSize(bar, box_channel); i++){
269 
270  dird = dDIRCLutReader->GetLutPixelAngle(bar, box_channel, i);
271  evtime = dDIRCLutReader->GetLutPixelTime(bar, box_channel, i);
272  pathid = dDIRCLutReader->GetLutPixelPath(bar, box_channel, i);
273 
274  // in MC we can check if the path of the LUT and measured photon are the same
275  bool samepath(false);
276  if(!locTruthDIRCHits.empty() && fabs(pathid - locTruthDIRCHits[0]->path)<0.0001)
277  samepath=true;
278 
279  for(int r=0; r<2; r++){
280  if(!reflected && r==1) continue;
281 
282  if(r) lenz = rlenz;
283  else lenz = dlenz;
284 
285  for(int u = 0; u < 4; u++){
286  if(u == 0) dir = dird;
287  if(u == 1) dir.SetXYZ( dird.X(),-dird.Y(), dird.Z());
288  if(u == 2) dir.SetXYZ( dird.X(), dird.Y(), -dird.Z());
289  if(u == 3) dir.SetXYZ( dird.X(),-dird.Y(), -dird.Z());
290  if(r) dir.SetXYZ( -dir.X(), dir.Y(), dir.Z());
291  if(dir.Angle(fnY1) < dCriticalAngle || dir.Angle(fnZ1) < dCriticalAngle) continue;
292 
293  luttheta = dir.Angle(TVector3(-1,0,0));
294  if(luttheta > TMath::PiOver2()) luttheta = TMath::Pi()-luttheta;
295  tangle = momInBar.Angle(dir);//-0.002; //correction
296 
297  double bartime = lenz/cos(luttheta)/DIRC_LIGHT_V;
298  double totalTime = bartime+evtime;
299 
300  // calculate time difference
301  double locDeltaT = totalTime-hitTime;
302 
303  if(DIRC_DEBUG_HISTS) {
304  dapp->RootWriteLock();
305  hTime->Fill(hitTime);
306  hCalc->Fill(totalTime);
307 
308  if(fabs(tangle-0.5*(locExpectedAngle[PiPlus]+locExpectedAngle[KPlus]))<0.2){
309  hDiff->Fill(locDeltaT);
310  hDiff_Pixel[box]->Fill(channel%dMaxChannels, locDeltaT);
311  if(samepath){
312  hDiffT->Fill(locDeltaT);
313  if(r) hDiffR->Fill(locDeltaT);
314  else hDiffD->Fill(locDeltaT);
315  }
316  }
317  dapp->RootUnLock();
318  }
319 
320  // save hits array which pass some lose time and angle criteria
321  if(fabs(locDeltaT) < 100.0 && fabs(tangle-0.5*(locExpectedAngle[PiPlus]+locExpectedAngle[KPlus]))<0.2) {
322  locDIRCPhoton.first = totalTime;
323  locDIRCPhoton.second = tangle;
324  locDIRCPhotons.push_back(locDIRCPhoton);
325  }
326 
327  // reject photons that are too far out of time
328  if(!r && fabs(locDeltaT)>DIRC_CUT_TDIFFD) continue;
329  if( r && fabs(locDeltaT)>DIRC_CUT_TDIFFR) continue;
330 
331  if(DIRC_DEBUG_HISTS) {
332  dapp->RootWriteLock();
333  //hDeltaThetaC[locPID]->Fill(tangle-locAngle);
334  //hDeltaThetaC_Pixel[locPID]->Fill(channel, tangle-locAngle);
335  dapp->RootUnLock();
336  }
337 
338  // remove photon candidates not used in likelihood
339  if(fabs(tangle-0.5*(locExpectedAngle[PiPlus]+locExpectedAngle[KPlus]))>0.05) continue;
340 
341  // save good photons to matched list
342  isGood = true;
343 
344  // count good photons
345  nPhotonsThetaC++;
346 
347  // calculate average ThetaC and DeltaT
348  meanThetaC += tangle;
349  meanDeltaT += locDeltaT;
350 
351  // calculate likelihood for each mass hypothesis
352  for(uint loc_j = 0; loc_j<dFinalStatePIDs.size(); loc_j++) {
353  logLikelihoodSum[dFinalStatePIDs[loc_j]] += TMath::Log( CalcLikelihood(locExpectedAngle[dFinalStatePIDs[loc_j]], tangle));
354  }
355 
356  }
357  } // end loop over reflections
358  } // end loop over nodes
359 
360  return locDIRCPhotons;
361 }
362 
363 // overloaded function when calculating outside LUT factory
364 vector<pair<double,double>> DDIRCLut::CalcPhoton(const DDIRCPmtHit *locDIRCHit, double locFlightTime, TVector3 posInBar, TVector3 momInBar, map<Particle_t, double> locExpectedAngle, double locAngle, Particle_t locPID, map<Particle_t, double> &logLikelihoodSum) const
365 {
366  int nPhotonsThetaC=0;
367  double meanThetaC=0.0, meanDeltaT=0.0;
368  bool isGood=false;
369  return CalcPhoton(locDIRCHit, locFlightTime, posInBar, momInBar, locExpectedAngle, locAngle, locPID, logLikelihoodSum, nPhotonsThetaC, meanThetaC, meanDeltaT, isGood);
370 }
371 
372 double DDIRCLut::CalcLikelihood(double locExpectedThetaC, double locThetaC) const {
373 
374  double locLikelihood = TMath::Exp(-0.5*( (locExpectedThetaC-locThetaC)/DIRC_SIGMA_THETAC * (locExpectedThetaC-locThetaC)/DIRC_SIGMA_THETAC ) ) + 0.00001;
375 
376  return locLikelihood;
377 }
378 
379 double DDIRCLut::CalcAngle(TVector3 momInBar, double locMass) const {
380  return acos(sqrt(momInBar.Mag()*momInBar.Mag() + locMass*locMass)/momInBar.Mag()/dIndex);
381 }
382 
383 map<Particle_t, double> DDIRCLut::CalcExpectedAngles(TVector3 momInBar) const {
384 
385  map<Particle_t, double> locExpectedAngles;
386  for(uint loc_i = 0; loc_i<dFinalStatePIDs.size(); loc_i++) {
387  locExpectedAngles[dFinalStatePIDs[loc_i]] = acos(sqrt(momInBar.Mag()*momInBar.Mag() + ParticleMass(dFinalStatePIDs[loc_i])*ParticleMass(dFinalStatePIDs[loc_i]))/momInBar.Mag()/dIndex);
388  }
389  return locExpectedAngles;
390 }
DApplication * dapp
vector< pair< double, double > > CalcPhoton(const DDIRCPmtHit *locDIRCHit, double locFlightTime, TVector3 posInBar, TVector3 momInBar, map< Particle_t, double > locExpectedAngle, double locAngle, Particle_t locPID, map< Particle_t, double > &logLikelihoodSum, int &nPhotonsThetaC, double &meanThetaC, double &meanDeltaT, bool &isGood) const
Definition: DDIRCLut.cc:212
static char * ParticleName_ROOT(Particle_t p)
Definition: particleType.h:851
double CalcAngle(TVector3 momInBar, double locMass) const
Definition: DDIRCLut.cc:379
Double_t x[NCHANNELS]
Definition: st_tw_resols.C:39
#define y
static char * ParticleType(Particle_t p)
Definition: particleType.h:142
double CalcLikelihood(double locExpectedThetaC, double locThetaC) const
Definition: DDIRCLut.cc:372
TH1D * py[NCHANNELS]
DDIRCLutReader * GetDIRCLut(unsigned int run_number)
static double ParticleMass(Particle_t p)
double sqrt(double)
DDIRCLut()
Definition: DDIRCLut.cc:17
bool CreateDebugHistograms()
Definition: DDIRCLut.cc:70
bool CalcLUT(TVector3 locProjPos, TVector3 locProjMom, const vector< const DDIRCPmtHit * > locDIRCHits, double locFlightTime, Particle_t locPID, shared_ptr< DDIRCMatchParams > &locDIRCMatchParams, const vector< const DDIRCTruthBarHit * > locDIRCBarHits, map< shared_ptr< const DDIRCMatchParams >, vector< const DDIRCPmtHit * > > &locDIRCTrackMatchParams) const
Definition: DDIRCLut.cc:122
map< Particle_t, double > CalcExpectedAngles(TVector3 momInBar) const
Definition: DDIRCLut.cc:383
TDirectory * dir
Definition: bcal_hist_eff.C:31
bool brun(JEventLoop *loop)
Definition: DDIRCLut.cc:57
union @6::@8 u
Particle_t
Definition: particleType.h:12