HighLAND
TPCFGDMatchEffSystematics.cxx
1 #include "TPCFGDMatchEffSystematics.hxx"
2 #include "CutUtils.hxx"
3 #include "SystematicUtils.hxx"
4 #include "VersioningUtils.hxx"
5 #include "SystId.hxx"
6 #include "Parameters.hxx"
7 
8 //#define DEBUG
9 
10 //********************************************************************
11 TPCFGDMatchEffSystematics::TPCFGDMatchEffSystematics(bool comp):BinnedParams("TPCFGDMatchEff",k1D_EFF_ASSYMMETRIC,versionUtils::Extension()){
12 //********************************************************************
13 
14  _computecounters=comp;
16  if (_computecounters)
18 
19  // In production 6 one uses ToF difference between two FGDs to reverse an object
20  // hence it has to be taken into account through matching systematics, if a track crosses two
21  // FGDs then the systematics should be applied to either of the FGD segments that has the few NNodes requirement
22  // or both
23 
24  // For the moment control with a parameter
25  _apply_both_FGD1_FGD2 = (bool)ND::params().GetParameterI("psycheSystematics.TPCFGDMatchEffSystematics.ApplyBoth_FGD1_FGD2");
26  _prod6_nnodes_cut = ND::params().GetParameterI("psycheSystematics.TPCFGDMatchEffSystematics.Prod6NNodesCut");
27 
28 }
29 
30 //********************************************************************
32 //********************************************************************
33 
34  if(_computecounters)
36 
37  // Get the SystBox for this event, and the appropriate selection and branch
39 
40 #ifdef DEBUG
41  std::cout << " TPCFGDMatchEffSystematics::ComputeWeight() " << std::endl;
42  std::cout << " Event " << static_cast<const AnaEventB&>(event).EventInfo.Event << std::endl;
43 #endif
44 
45  Weight_h eventWeight=1;
46 
47  if( !versionUtils::prod6_systematics){
48  // Loop over all charged trajectories traversing TPC or FGD
49  for (Int_t itrue=0;itrue<SystBox->nRelevantTrueObjects;itrue++){
50  AnaTrueParticleB* trueTrack = static_cast<AnaTrueParticleB*>(SystBox->RelevantTrueObjects[itrue]);
51 
52  AnaTrackB* recoTrack = static_cast<AnaTrackB*>(SystBox->RelevantTrueObjectsReco[itrue]);
53  bool tpc_rec_exists=false;
54 
55  // Use by default the true momentum
56  Float_t p0 = trueTrack->Momentum;
57  if (recoTrack) p0 = recoTrack->Momentum;
58 
59  // Retrieve the systematic
60  BinnedParamsParams params;
61  Int_t index;
62  if (!GetBinValues(p0,params,index)) continue;
63 
64  //here the big inefficiency that is observed in MC and in Data is not trusted.
65  //Because the values jump from 0.7 to 0.98 from one bin to the other,
66  //we decided to interpolate the inefficiency linearly to the next bin.
67  if(p0<100 ){
68  BinnedParamsParams params1;
69  GetParametersForBin(1,params1);
70  Float_t mMCANA = params.meanMCANA + p0/100*(params1.meanMCANA - params.meanMCANA);
71  Float_t mMC = params.meanMC + p0/100*(params1.meanMC - params.meanMC);
72  Float_t mDATA = params.meanDATA + p0/100*(params1.meanDATA - params.meanDATA);
73  Float_t sigMCl = params1.sigmaMCl + (100-p0)/100.*params.sigmaMCl;
74  Float_t sigMCh = params1.sigmaMCh + (100-p0)/100.*params.sigmaMCh;
75  Float_t sigDATAl = params1.sigmaDATAl + (100-p0)/100.*params.sigmaDATAl;
76  Float_t sigDATAh = params1.sigmaDATAh + (100-p0)/100.*params.sigmaDATAh;
77  params.meanMCANA = mMCANA;
78  params.meanMC = mMC;
79  params.meanDATA = mDATA;
80  params.sigmaMCl = sigMCl;
81  params.sigmaMCh = sigMCh;
82  params.sigmaDATAl = sigDATAl;
83  params.sigmaDATAh = sigDATAh;
84  }
85 
86  // Efficiency weight when a complete TPC-FGD track exists
87  bool found=false;
88  if(recoTrack) found=true;
89  // else if(tpc_rec_exists || inFGDTPCseg) found=false;
90  else if(tpc_rec_exists) found=false;
91  else continue;
92 
93  eventWeight *= systUtils::ComputeEffLikeWeight(found, toy, GetIndex(), index, params);
94 
95  if(_computecounters)
96  UpdateEfficiencyCounter(index,found);
97  }
98  }
99  else{
100  /// for long tracks crossing the FGD, TPC-FGD matching is working at 100% in production6 therefore we only consider for production 6 very short tracks starting at the edge of the FGD. This is the case that has not been taken into account with the TPC-FGD matching package which use through-going muons crossing TPC1 and TPC2 or TPC2 and TPC3.
101  /// for very short tracks in the FGD starting at the edge, tpc-fgd matching will depend on the efficiency to really get a hit in one of the two layers under consideration. Therefore the following propagation.
102  ////// NHITS
103  /// assume we observe nhits in the reco tracks.
104  /// 1) we have the possibility that there were really nhits before (we did not lose anything:
105  /// probability is :p = eff^nhits
106  /// 2) we have the possibility that one hit is lost, so there nhits+1 before
107  /// probability is :p= (nhits+1)*eff^nhits*(1-eff)
108  /// 3) we lost 2 hits, so there were nhits+2 before
109  /// probability is :p= (nhits+2)*(nhits+1)/2*eff^nhits*(1-eff)^2
110  /// sum p= eff^nhits*[1+(nhits+1)*(1-eff)+(nhits+2)*(nhits+1)/2*(1-eff)^2]
111  /// = eff^nhits*[1+(nhhits+1)(1-eff)[1+(nhits+2)/2*(1-eff)]]
112 
113  //if( SystBox->nRelevantRecObjects == 0 ) return eventWeight;
114  // Loop over relevant tracks for this systematic
115 
116  for (Int_t itrk = 0; itrk < SystBox->nRelevantRecObjects; itrk++){
117  AnaTrackB* track = static_cast<AnaTrackB*>(SystBox->RelevantRecObjects[itrk]);
118 
119 #ifdef DEBUG
120  std::cout << " Track " << itrk << std::endl;
121 #endif
122 
123  if (!track) continue;
124 
125  // For example in numuCC inclusive selection, only the Candidate is important at first order
126  if (!sel.IsRelevantRecObjectForSystematicInToy(event, box, track, SystId::kTpcFgdMatchEff, box.SuccessfulBranch)) continue;
127 
128 
129  AnaParticleB* FGD1Segment = NULL;
130  AnaParticleB* FGD2Segment = NULL;
131 
132  bool isInFGD1 = anaUtils::InFiducialVolume(SubDetId::kFGD1, track->PositionStart);
133  bool isInFGD2 = anaUtils::InFiducialVolume(SubDetId::kFGD2, track->PositionStart);
134 
135  if (!isInFGD1 && !isInFGD2) return false;
136 
137  if (isInFGD1 || _apply_both_FGD1_FGD2){
138  FGD1Segment = anaUtils::GetSegmentWithMostNodesInDet(*track, SubDetId::kFGD1);
139  }
140 
141  if (isInFGD2 || _apply_both_FGD1_FGD2){
142  FGD2Segment = anaUtils::GetSegmentWithMostNodesInDet(*track, SubDetId::kFGD2);
143  }
144 
145  if (!FGD1Segment && !FGD2Segment) continue;
146 
147  // Primary candidate
148  AnaParticleB* prim_cand = isInFGD1 ? FGD1Segment : FGD2Segment;
149  // Secondary candidate
150  AnaParticleB* sec_cand = isInFGD1 ? FGD2Segment : FGD1Segment;
151 
152  eventWeight *= GetWeight(static_cast<AnaFGDParticleB*>(prim_cand), toy);
153 
154 #ifdef DEBUG
155  Weight_h weight_tmp = GetWeight(static_cast<AnaFGDParticleB*>(prim_cand), toy);
156  std::cout << "weight prim corr " << weight_tmp.Correction << " syst " << weight_tmp.Systematic << std::endl;
157 #endif
158  if (_apply_both_FGD1_FGD2){
159 #ifdef DEBUG
160  std::cout << " applying second weight " << std::endl;
161  if (sec_cand){
162  std::cout << " FGD " << SubDetId::GetSubdetectorEnum(sec_cand->Detector) <<std::endl;
163  }
164  else
165  std::cout << "does not exist " << std::endl;
166 #endif
167  eventWeight *= GetWeight(static_cast<AnaFGDParticleB*>(sec_cand), toy);
168 
169 #ifdef DEBUG
170  Weight_h weight_tmp = GetWeight(static_cast<AnaFGDParticleB*>(sec_cand), toy);
171  std::cout << "weight second corr " << weight_tmp.Correction << " syst " << weight_tmp.Systematic << std::endl;
172 #endif
173 
174 
175  }
176  }
177  }
178 
179 #ifdef DEBUG
180  std::cout << "weight final event corr " << eventWeight.Correction << " syst " << eventWeight.Systematic << std::endl;
181 #endif
182 
183  return eventWeight;
184 }
185 //**************************************************
187 //**************************************************
188 
189  Weight_h weight;
190  if (!FGDSegment) return weight;
191 
192  Float_t nn = FGDSegment->NNodes;
193 
194  // Do nothing if nnodes above the cut
195  if (nn > _prod6_nnodes_cut) return weight;
196 
197  int fgdnum = 0;
198 
199  if (SubDetId::GetSubdetectorEnum(FGDSegment->Detector) == SubDetId::kFGD1)
200  fgdnum = 1;
201  else if (SubDetId::GetSubdetectorEnum(FGDSegment->Detector) == SubDetId::kFGD2)
202  fgdnum = 2;
203 
204  // Read the systematic source parameters
205  BinnedParamsParams params;
206  int index;
207 
208  if (!GetBinValues(fgdnum, params, index)) return weight;
209 
210  Weight_h eff_w = systUtils::ComputeEffLikeWeight(true, toy, GetIndex(), 0, params);
211 
212  Float_t Pnom = params.meanMCANA;
213 
214  Weight_h Pineff = 1-eff_w; //this is true, only if assume that effMC=1
215 
216  weight *= Weight_h(TMath::Power(eff_w.Correction,nn)*(1.+(nn+1)*(Pineff.Correction)*(((nn+2)/2.)*Pineff.Correction) )/ (1.+(nn+1)*(1-Pnom)*((nn+2)/2.*(1-Pnom))),
217  TMath::Power(eff_w.Systematic,nn)*(1.+(nn+1)*(Pineff.Systematic)*(((nn+2)/2.)*Pineff.Systematic) )/ (1.+(nn+1)*(1-Pnom)*((nn+2)/2.*(1-Pnom))));
218 
219 
220  // std::cout<<" eff_w "<<eff_w<<" effmc "<<params.meanMC<<" effdata "<<params.meanDATA<< std::endl;
221  // std::cout<<" nnodes "<<nnodes<<" pos "<<track->PositionStart[2]<<" truepos "<<track->GetTrueParticle()->Position[2]<<" weight "<<eventWeight<<std::endl;
222 
223 
224 
225 
226  return weight;
227 
228 }
229 
230 
231 //THIS IS FOR PROD6 PROP
232 //**************************************************
234 //**************************************************
235 
236  (void)event;
237 
238  const AnaTrackB& track = *static_cast<const AnaTrackB*>(&recObj);
239 
240  if(!track.TrueObject) return false;
241  if( versionUtils::prod6_systematics){
242  if(track.nFGDSegments == 0) return false;
243  AnaParticleB* FGD1Segment = NULL;
244  AnaParticleB* FGD2Segment = NULL;
245 
246  bool isInFGD1 = anaUtils::InFiducialVolume(SubDetId::kFGD1, track.PositionStart);
247  bool isInFGD2 = anaUtils::InFiducialVolume(SubDetId::kFGD2, track.PositionStart);
248 
249  if (!isInFGD1 && !isInFGD2) return false;
250 
251  if (isInFGD1 || _apply_both_FGD1_FGD2){
252  FGD1Segment = anaUtils::GetSegmentWithMostNodesInDet(track,SubDetId::kFGD1);
253  }
254  if (isInFGD2 || _apply_both_FGD1_FGD2){
255  FGD2Segment = anaUtils::GetSegmentWithMostNodesInDet(track,SubDetId::kFGD2);
256  }
257 
258  if (!FGD1Segment && !FGD2Segment) return false;
259 
260  // Primary candidate
261  AnaParticleB* prim_cand = isInFGD1 ? FGD1Segment : FGD2Segment;
262  // Secondary candidate
263  AnaParticleB* sec_cand = isInFGD1 ? FGD2Segment : FGD1Segment;
264 
265  if (!prim_cand) return false;
266 
267  Int_t nnodes = prim_cand->NNodes;
268 
269  if (_apply_both_FGD1_FGD2 && sec_cand)
270  nnodes = std::min(nnodes, sec_cand->NNodes);
271 
272 
273  //only consider the very short case tracks, since those are suceptible to change something in data
274  //normally one hit in the FGD is needed so that there is a matching,
275  // std::cout<<" nn "<<nnodes<<std::endl;
276  if (nnodes > _prod6_nnodes_cut) return false;
277  return true;
278  }
279  else{
280  if (track.Momentum < 30) return false;
281  return true;
282  }
283 
284 }
285 //THIS IS FOR PROD5 PROP
286 //********************************************************************
288 //********************************************************************
289 
290  // True track should always exist
291  if(trueTrack.ID != track.TrueObject->ID) return false;
292 
293  // Check for a good TPC-FGD track
294  bool tinFGD1 = SubDetId::GetDetectorUsed(track.Detector, SubDetId::kFGD1);
295  bool tinFGD2 = SubDetId::GetDetectorUsed(track.Detector, SubDetId::kFGD2);
296  bool tinTPC1 = SubDetId::GetDetectorUsed(track.Detector, SubDetId::kTPC1);
297  bool tinTPC2 = SubDetId::GetDetectorUsed(track.Detector, SubDetId::kTPC2);
298  bool tinTPC3 = SubDetId::GetDetectorUsed(track.Detector, SubDetId::kTPC3);
299 
300  // Complete TPC-FGD track found
301  if((tinFGD1 && (tinTPC1 || tinTPC2)) || (tinFGD2 && (tinTPC2 || tinTPC3))) return true;
302 
303  return false;
304 }
305 
306 //********************************************************************
307 Int_t TPCFGDMatchEffSystematics::GetRelevantRecObjectGroups(const SelectionBase& sel, Int_t ibranch, Int_t* IDs) const{
308 //********************************************************************
309 
310  SubDetId_h det = sel.GetDetectorFV(ibranch);
311 
312  if( versionUtils::prod6_systematics){
313  if (det == SubDetId::kFGD1){
314  IDs[0] = EventBoxTracker::kTracksWithTPCInFGD1FV;
315  return 1;
316  }
317  else if (det == SubDetId::kFGD2){
318  IDs[0] = EventBoxTracker::kTracksWithTPCInFGD2FV;
319  return 1;
320  }
321  else if (det == SubDetId::kFGD){
322  IDs[0] = EventBoxTracker::kTracksWithTPCInFGD1FV;
323  IDs[1] = EventBoxTracker::kTracksWithTPCInFGD2FV;
324  return 2;
325  }
326  }
327  else{
328  if (det == SubDetId::kFGD1){
329  IDs[0] = EventBoxTracker::kTracksWithTPCorFGD1;
330  return 1;
331  }
332  else if (det == SubDetId::kFGD2){
333  IDs[0] = EventBoxTracker::kTracksWithTPCorFGD2;
334  return 1;
335  }
336  else if (det == SubDetId::kFGD){
337  IDs[0] = EventBoxTracker::kTracksWithTPCorFGD1;
338  IDs[1] = EventBoxTracker::kTracksWithTPCorFGD2;
339  return 2;
340  }
341  }
342 
343  return 0;
344 }
345 
346 //********************************************************************
347 Int_t TPCFGDMatchEffSystematics::GetRelevantTrueObjectGroups(const SelectionBase& sel, Int_t ibranch, Int_t* IDs) const{
348 //********************************************************************
349 
350  SubDetId_h det = sel.GetDetectorFV(ibranch);
351 
352  //may change in future
353  if (det == SubDetId::kFGD1){
354  IDs[0] = EventBoxTracker::kTrueParticlesChargedInTPCorFGDInBunch;
355  return 1;
356  }
357  else if (det == SubDetId::kFGD2){
358  IDs[0] = EventBoxTracker::kTrueParticlesChargedInTPCorFGDInBunch;
359  return 1;
360  }
361  else if (det == SubDetId::kFGD){
362  IDs[0] = EventBoxTracker::kTrueParticlesChargedInTPCorFGDInBunch;
363  return 1;
364  }
365 
366  return 0;
367 }
Float_t PositionStart[4]
The reconstructed start position of the particle.
unsigned long Detector
Int_t GetIndex() const
Return the index of this systematic.
int GetParameterI(std::string)
Get parameter. Value is returned as integer.
Definition: Parameters.cxx:217
Weight_h ComputeWeight(const ToyExperiment &, const AnaEventC &, const ToyBoxB &)
Apply the systematic.
Int_t SelectionEnabledIndex
The enabled index of this selection this ToyBox belongs to.
Definition: ToyBoxB.hxx:49
Int_t NNodes
The number of nodes in the reconstructed object.
SystBoxB * GetSystBox(const AnaEventC &event, Int_t isel=0, Int_t ibranch=0) const
Get the SystBox corresponding to a selection, branch and event.
void SetNParameters(int N)
Set the number of systematic parameters associated to this systematic.
AnaTrueObjectC * TrueObject
The link to the true oject that most likely generated this reconstructed object.
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
Weight_h GetWeight(const AnaFGDParticleB *FGDSegment, const ToyExperiment &toy)
Float_t Momentum
The initial momentum of the true particle.
bool CheckTrueRecoAssociation(const AnaTrueObjectC &trueTrack, const AnaRecObjectC &track) const
Check the true-reco association.
Int_t ID
The ID of the trueObj, which corresponds to the ID of the TTruthParticle that created it...
bool GetBinValues(Float_t value, Float_t &mean, Float_t &sigma)
Gets the bin values for a 1D source.
Int_t GetRelevantRecObjectGroups(const SelectionBase &sel, Int_t ibranch, Int_t *IDs) const
Get the TrackGroup IDs array for this systematic.
Float_t meanDATA
The mean value for each of the systematic parameters of the control sample.
bool UpdateEfficiencyCounter(Int_t index, bool correct)
Update the efficiency variables _ncorrect and _nwrong.
Float_t Momentum
The reconstructed momentum of the particle, at the start position.
Representation of a true Monte Carlo trajectory/particle.
virtual bool IsRelevantRecObjectForSystematicInToy(const AnaEventC &, const ToyBoxB &, AnaRecObjectC *, SystId_h syst_index, Int_t branch=0) const
Is this track relevant for a given systematic (after selection, called for each toy) ...
Int_t SuccessfulBranch
The branch that is successful for this toy in the selection this ToyBox belongs to.
Definition: ToyBoxB.hxx:46
Float_t meanMC
The mean value for each of the systematic parameters of the control sample.
Representation of a global track.
Int_t nRelevantTrueObjects
Array of Relevant True RecObjects for each systematic.
Definition: SystBoxB.hxx:24
static SubDetId::SubDetEnum GetSubdetectorEnum(unsigned long BitField)
Get the single subdetector that this track is from.
Definition: SubDetId.cxx:165
Representation of a FGD segment of a global track.
AnaRecObjectC ** RelevantTrueObjectsReco
Definition: SystBoxB.hxx:29
Float_t meanMCANA
The mean value for each of the systematic parameters of the analysis sample.
int nFGDSegments
How many FGD tracks are associated with this track.
bool IsRelevantRecObject(const AnaEventC &event, const AnaRecObjectC &track) const
Is this track relevant for this systematic ?
Float_t sigmaDATAl
The sigma value for each of the systematic parameters of the control sample /// with possibility of a...
Int_t nRelevantRecObjects
----—— Relevant rec objects and true objects for each systematic ------------—— ...
Definition: SystBoxB.hxx:20
void InitializeEfficiencyCounter()
Initialize counters.
bool GetParametersForBin(Int_t index, Float_t &mean, Float_t &sigma)
Gets the bin values for a source provided the bin index.
Int_t GetRelevantTrueObjectGroups(const SelectionBase &sel, Int_t ibranch, Int_t *IDs) const
Get the TrueTrackGroup IDs array for this systematic.
bool InFiducialVolume(SubDetId::SubDetEnum det, const Float_t *pos, const Float_t *FVdefmin, const Float_t *FVdefmax)
AnaParticleB * GetSegmentWithMostNodesInDet(const AnaTrackB &track, SubDetId::SubDetEnum det)
Method to get the subtrack with most nodes in a given detector.
Representation of a reconstructed particle (track or shower).
Int_t GetNBins()
Get the number of bins.
SubDetId_h GetDetectorFV(Int_t ibranch=0) const
Get the detector in which the Fiducial Volume is defined.