HighLAND
HighlandPIDUtils.cxx
1 #include "HighlandAnalysisUtils.hxx"
2 #include <stdio.h>
3 #include <math.h>
4 
5 const unsigned int NMAXPARTICLESWITHTPC = NMAXPARTICLES;
6 
7 //********************************************************************
8 void anaUtils::ComputeTPCPullIncludingKaon(const AnaTPCParticleB &trackB, Float_t* pulls) {
9 //********************************************************************
10 
11  // cast the track
12  const AnaTPCParticle& track = *static_cast<const AnaTPCParticle*>(&trackB);
13 
14  // compute pulls for the standard hypotheses using the method in psyche utils
15  anaUtils::ComputeTPCPull(track, pulls);
16 
17  // compute pull for kaon hypothesis
18  pulls[4] = ((track.dEdxMeas - track.dEdxexpKaon) / track.dEdxSigmaKaon);
19 }
20 
21 //********************************************************************
22 void anaUtils::GetPIDLikelihoodIncludingKaon(const AnaTrackB& track, Float_t* hypo, bool prod5Cut) {
23 //********************************************************************
24 
25  UInt_t itrk = track.Index;
26 
27  if( itrk >= NMAXPARTICLESWITHTPC ) return; // Protection against values out of the vector.
28 
29  Double_t prob[5]={1,1,1,1,1};
30  Double_t tmp_prob[3][5];
31  Double_t total_prob=0;
32  bool found=false;
33 
34  AnaTPCParticleB* segmentsInTPC[3];
35  for(int i = 0; i < 3; ++i){
36  segmentsInTPC[i] = NULL;
37  for (Int_t j=0;j<5;j++){
38  hypo[j]=-1;
39  tmp_prob[i][j] = 1;
40  }
41  }
42  // Get the closest TPC. We should make sure that at least the segment in that TPC has the proper PID info
44 
45  // Loop over TPC segments
46  for (int j = 0; j < track.nTPCSegments; ++j){
47  AnaTPCParticleB* TPCSegment = track.TPCSegments[j];
48  if (!TPCSegment) continue;
49 
50  // Only segments passing the TPC track quality cut will contribute to the likelihood
51  // Was not applied for production 5 BANFF analysis
52  if(!prod5Cut) if (!cutUtils::TPCTrackQualityCut(*TPCSegment)) continue;
53 
54  // Require valid values for all quantities involved
55  if( TPCSegment->dEdxexpMuon==-0xABCDEF || TPCSegment->dEdxexpEle==-0xABCDEF || TPCSegment->dEdxexpPion==-0xABCDEF || TPCSegment->dEdxexpProton==-0xABCDEF) continue;
56  if( TPCSegment->dEdxMeas ==-0xABCDEF ) continue;
57  if( TPCSegment->dEdxexpMuon==-99999 || TPCSegment->dEdxexpEle==-99999 || TPCSegment->dEdxexpPion==-99999 || TPCSegment->dEdxexpProton==-99999) continue;
58  if( TPCSegment->dEdxMeas ==-99999 ) continue;
59 
60  // Require valid values for kaon quantities (these are not yet in psyche)
61  AnaTPCParticle* TPCSegmentK = (AnaTPCParticle*)TPCSegment;
62  if( TPCSegmentK->dEdxexpKaon==-0xABCDEF || TPCSegmentK->dEdxMeas ==-0xABCDEF ) continue;
63  if( TPCSegmentK->dEdxexpKaon==-99999 || TPCSegmentK->dEdxMeas ==-99999 ) continue;
64 
65  Float_t pulls[5];
66  // Pulls in order: Muon, Electron, Proton, Pion, Kaon
67  anaUtils::ComputeTPCPullIncludingKaon(*TPCSegment,pulls);
68  Float_t pullmu = pulls[0];
69  Float_t pullele = pulls[1];
70  Float_t pullp = pulls[2];
71  Float_t pullpi = pulls[3];
72  Float_t pullka = pulls[4];
73 
74  if (!TMath::Finite(pullmu) || !TMath::Finite(pullele) || !TMath::Finite(pullp) || !TMath::Finite(pullpi) || !TMath::Finite(pullka)) continue;
75  if (pullmu != pullmu || pullele != pullele || pullp != pullp || pullpi != pullpi || pullka != pullka) continue;
76 
78 
79  // To avoid mismatching between FlatTree and oaAnalysis we allow only one segment per TPC to be included in the likelihood, the one with more nodes
80  if (segmentsInTPC[det-2]){
81  if (TPCSegment->NNodes > segmentsInTPC[det-2]->NNodes){
82  segmentsInTPC[det-2] = TPCSegment;
83  tmp_prob[det-2][0] = exp(-(pullmu*pullmu)/2);
84  tmp_prob[det-2][1] = exp(-(pullele*pullele)/2);
85  tmp_prob[det-2][2] = exp(-(pullp*pullp)/2);
86  tmp_prob[det-2][3] = exp(-(pullpi*pullpi)/2);
87  tmp_prob[det-2][4] = exp(-(pullka*pullka)/2);
88  }
89  }
90  else{
91  segmentsInTPC[det-2] = TPCSegment;
92  tmp_prob[det-2][0] = exp(-(pullmu*pullmu)/2);
93  tmp_prob[det-2][1] = exp(-(pullele*pullele)/2);
94  tmp_prob[det-2][2] = exp(-(pullp*pullp)/2);
95  tmp_prob[det-2][3] = exp(-(pullpi*pullpi)/2);
96  tmp_prob[det-2][4] = exp(-(pullka*pullka)/2);
97  }
98  }
99 
100  // Loop over all segments contributing to the likelihood and compute it
101  for (int tpc=0;tpc<3;tpc++){
102  if (segmentsInTPC[tpc]){
103  // The pull should be already corrected by all corrections (CT and CT expected)
104  prob[0] *= tmp_prob[tpc][0];
105  prob[1] *= tmp_prob[tpc][1];
106  prob[2] *= tmp_prob[tpc][2];
107  prob[3] *= tmp_prob[tpc][3];
108  prob[4] *= tmp_prob[tpc][4];
109 
110  if (SubDetId::GetDetectorUsed(segmentsInTPC[tpc]->Detector, closesttpc)) found = true;
111  }
112  }
113 
114  // If at least the segment in the closest TPC has a valid PID info
115  if (found){
116  for (int h=0;h<5;h++){
117  total_prob += prob[h];
118  }
119 
120  if (total_prob>0){
121  for (int h=0;h<5;h++){
122  hypo[h] = prob[h]/total_prob;
123  }
124  }
125  }
126  return;
127 }
128 
129 //********************************************************************
130 Float_t anaUtils::GetPIDLikelihoodIncludingKaon(const AnaTrackB& track, Int_t hypo, bool prod5Cut) {
131 //********************************************************************
132 
133  if( hypo >= 5 ) return -1.e+6;
134 
135  Float_t Likelihood[5];
136  GetPIDLikelihoodIncludingKaon(track,Likelihood,prod5Cut);
137  return Likelihood[hypo];
138 }
139 
Float_t dEdxexpMuon
Expected dE/dx for a muon, based on the reconstructed momentum.
unsigned long Detector
Float_t dEdxexpProton
Expected dE/dx for a proton, based on the reconstructed momentum.
void ComputeTPCPullIncludingKaon(const AnaTPCParticleB &track, Float_t *pulls)
Function to recompute the pull for a TPC track segment including the kaon hypothesis.
Int_t NNodes
The number of nodes in the reconstructed object.
SubDetId::SubDetEnum GetClosestTPC(const AnaTrackB &track)
For tracks that start in the FGD, get the closest TPC in the direction of the track.
AnaTPCParticleB * TPCSegments[NMAXTPCS]
The TPC segments that contributed to this global track.
static bool GetDetectorUsed(unsigned long BitField, SubDetId::SubDetEnum det)
Method to see if a certain subdetector or subdetector system is used.
Definition: SubDetId.cxx:40
Float_t GetPIDLikelihoodIncludingKaon(const AnaTrackB &track, Int_t hypo, bool prod5Cut=0)
Float_t dEdxexpPion
Expected dE/dx for a pion, based on the reconstructed momentum.
Float_t dEdxexpEle
Expected dE/dx for an electron, based on the reconstructed momentum.
Int_t Index
The index of this particle track in the vector of particles. TODO: Not sure it is needed (only use in...
int nTPCSegments
How many TPC tracks are associated with this track.
Float_t dEdxSigmaKaon
Expected error on the dE/dx measurement, for the proton hypothesis.
SubDetEnum
Enumeration of all detector systems and subdetectors.
Definition: SubDetId.hxx:25
Float_t dEdxMeas
dE/dx as measured by the TPC.
Representation of a global track.
Float_t ComputeTPCPull(const AnaTPCParticleB &track, const std::string &particle)
Function to recompute the pull for a TPC track segment.
static SubDetId::SubDetEnum GetSubdetectorEnum(unsigned long BitField)
Get the single subdetector that this track is from.
Definition: SubDetId.cxx:165
Representation of a TPC segment of a global track.
Representation of a TPC segment of a global track.
Float_t dEdxexpKaon
Expected dE/dx for a proton, based on the reconstructed momentum.