ProtonIdentification_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 // Class: ProtonIdentification
3 // Module Type: analyzer
4 // File: ProtonIdentification_module.cc
5 //
6 // Generated at Sun Mar 24 09:05:02 2013 by Tingjun Yang using artmod
7 // from art v1_02_06.
8 //
9 // Using AnaTree as base, have written a module to compare reconstruction
10 // algorithm efficiencies.
11 //
12 // Thomas Karl Warburton
13 // k.warburton@sheffield.ac.uk
14 //
15 ////////////////////////////////////////////////////////////////////////
16 
17 // Framework includes
21 #include "fhiclcpp/ParameterSet.h"
26 #include "art_root_io/TFileService.h"
27 #include "art_root_io/TFileDirectory.h"
29 
30 // LArSoft includes
46 
50 
53 
56 
57 // ROOT includes
58 #include "TTree.h"
59 #include "TTimeStamp.h"
60 #include "TLorentzVector.h"
61 #include "TH2F.h"
62 #include "TEfficiency.h"
63 #include "TNtuple.h"
64 #include "TFile.h"
65 
66 //standard library includes
67 #include <map>
68 #include <iostream>
69 #include <iomanip>
70 #include <sstream>
71 #include <cmath>
72 #include <memory>
73 #include <limits> // std::numeric_limits<>
74 
75 const int kMaxHits = 250;
76 
79 }
80 
82 public:
83  explicit ProtonIdentification(fhicl::ParameterSet const & p);
84  virtual ~ProtonIdentification();
85 
86  void analyze(art::Event const & e) override;
87 
88  void beginRun(art::Run const& run) override;
89  void beginJob() override;
90  void endJob() override;
91  void endRun(art::Run const&) override;
92  //void reconfigure(fhicl::ParameterSet const & p) ;
93 
94 private:
95 
96  void ResetVars();
97  void MCTruthInformation ( detinfo::DetectorClocksData const& clockData, const simb::MCParticle *particle );
98 
99  void TrackBoundaries( TVector3 larStart, TVector3 larEnd );
100  double CalcDist( double X1, double Y1, double Z1, double X2, double Y2, double Z2 );
101  double CalcPIDA( std::vector<const anab::Calorimetry*> calos );
102  double PIDAFunc( double dedx, double resrng );
103 
104  // The T0 variables
107  // Some angular variables
110 
111  // The TPC boundaries
112  // MinX, MaxX, MinY, MaxY, MinZ, MaxZ
113  double boundaries[6]; // For use in finding detector boundaries.
114 
115  // Some global variables for what I have
117  int AllBad = 0, MuonBad = 0, ProtonBad = 0, GammaBad = 0, ElectronBad=0, OtherBad = 0;
118  int AllAll = 0, MuonAll = 0, ProtonAll = 0, GammaAll = 0, ElectronAll=0, OtherAll = 0;
120 
121  // My exported TTree
122  TTree *fRecoTree;
123  // MC variables
128  // Reco variables
136 
137 
138  // A soley truth tree...
139  TTree* fTrueTree;
141  double True_Length[1000], True_StartX[1000], True_StartY[1000], True_StartZ[1000], True_EndX[1000], True_EndY[1000], True_EndZ[1000];
142 
143  // Handles
147 
148  // Some variables
150  double WindowSize;
151 
152  // Parameter List
161  int Verbose;
162 };
163 // ********************************** Begin Run *******************************************************
165 
166 }
167 // *********************************** Begin Job ********************************************************
169 {
170  // --------- Working out detector dimensions ----------------
171  boundaries[0] = boundaries[2] = boundaries[4] = DBL_MAX;
172  boundaries[1] = boundaries[3] = boundaries[5] = -DBL_MAX;
173 
174  auto const* geom = lar::providerFrom<geo::Geometry>();
175  for (geo::TPCGeo const& TPC: geom->IterateTPCs()) {
176  // get center in world coordinates
177  const double origin[3] = {0.};
178  double center[3] = {0.};
179  TPC.LocalToWorld(origin, center);
180  //double tpcDim[3] = {TPC.ActiveHalfWidth(), TPC.ActiveHalfHeight(), 0.5*TPC.ActiveLength() };
181  double tpcDim[3] = {TPC.HalfWidth(), TPC.HalfHeight(), 0.5*TPC.Length() };
182  if( center[0] - tpcDim[0] < boundaries[0] ) boundaries[0] = center[0] - tpcDim[0];
183  if( center[0] + tpcDim[0] > boundaries[1] ) boundaries[1] = center[0] + tpcDim[0];
184  if( center[1] - tpcDim[1] < boundaries[2] ) boundaries[2] = center[1] - tpcDim[1];
185  if( center[1] + tpcDim[1] > boundaries[3] ) boundaries[3] = center[1] + tpcDim[1];
186  if( center[2] - tpcDim[2] < boundaries[4] ) boundaries[4] = center[2] - tpcDim[2];
187  if( center[2] + tpcDim[2] > boundaries[5] ) boundaries[5] = center[2] + tpcDim[2];
188  //std::cout << boundaries[0] << " " << boundaries[1] << " " << boundaries[2] << " " << boundaries[3] << " " <<boundaries[4] << " " << boundaries[5] << std::endl;
189  } // for all TPC
190  //std::cout << boundaries[0] << " " << boundaries[1] << " " << boundaries[2] << " " << boundaries[3] << " " <<boundaries[4] << " " << boundaries[5] << std::endl;
191 
192  // Implementation of optional member function here.
194  fRecoTree = tfs->make<TTree>("ReconstructedTree","analysis tree");
195  // The Truth information
196  fRecoTree->Branch("MCPdgCode" ,&MCPdgCode ,"MCPdgCode/I" );
197  fRecoTree->Branch("MCTPCLength" ,&MCTPCLength ,"MCTPCLength/D" );
198  fRecoTree->Branch("MCTrackId" ,&MCTrackId ,"MCTrackId/I" );
199  fRecoTree->Branch("MCEnergy" ,&MCEnergy ,"MCEnergy/D" );
200  fRecoTree->Branch("MCEnergyDeposited",&MCEnergyDeposited,"MCEnergyDeposited/D");
201  fRecoTree->Branch("MCStartInTPC" ,&MCStartInTPC ,"MCStartInTPC/B" );
202  fRecoTree->Branch("MCEndInTPC" ,&MCEndInTPC ,"MCEndInTPC/B" );
203  fRecoTree->Branch("MCCorOrient" ,&MCCorOrient ,"MCCorOrient/B" );
204  fRecoTree->Branch("MCContainment" ,&MCContainment ,"MCContainment/I" );
205  fRecoTree->Branch("MCIsPrimary" ,&MCIsPrimary ,"MCIsPrimary/I" );
206  fRecoTree->Branch("MCPIDA" ,&MCPIDA ,"MCPIDA/D" );
207  fRecoTree->Branch("MCStartX" ,&MCStartX ,"MCStartX/D" );
208  fRecoTree->Branch("MCStartY" ,&MCStartY ,"MCStartY/D" );
209  fRecoTree->Branch("MCStartZ" ,&MCStartZ ,"MCStartZ/D" );
210  fRecoTree->Branch("MCEndX" ,&MCEndX ,"MCEndX/D" );
211  fRecoTree->Branch("MCEndY" ,&MCEndY ,"MCEndY/D" );
212  fRecoTree->Branch("MCEndZ" ,&MCEndZ ,"MCEndZ/D" );
213  // Now for the reco stuff...
214  fRecoTree->Branch("TrackLength" ,&TrackLength ,"TrackLength/D" );
215  fRecoTree->Branch("TrackHits" ,&TrackHits ,"TrackHits[3]/I" );
216  fRecoTree->Branch("MatchedTrackID" ,&MatchedTrackID ,"MatchedTrackID/I" );
217  fRecoTree->Branch("CorrectedStartX" ,&CorrectedStartX ,"CorrectedStartX/D" );
218  fRecoTree->Branch("CorrectedStartY" ,&CorrectedStartY ,"CorrectedStartY/D" );
219  fRecoTree->Branch("CorrectedStartZ" ,&CorrectedStartZ ,"CorrectedStartZ/D" );
220  fRecoTree->Branch("CorrectedEndX" ,&CorrectedEndX ,"CorrectedEndX/D" );
221  fRecoTree->Branch("CorrectedEndY" ,&CorrectedEndY ,"CorrectedEndY/D" );
222  fRecoTree->Branch("CorrectedEndZ" ,&CorrectedEndZ ,"CorrectedEndZ/D" );
223  fRecoTree->Branch("PIDA" ,&PIDA ,"PIDA/D" );
224  fRecoTree->Branch("PIDA_Plane0" ,&PIDA_Plane0 ,"PIDA_Plane0/D" );
225  fRecoTree->Branch("PIDA_Plane1" ,&PIDA_Plane1 ,"PIDA_Plane1/D" );
226  fRecoTree->Branch("PIDA_Plane2" ,&PIDA_Plane2 ,"PIDA_Plane2/D" );
227  fRecoTree->Branch("RecoStartInTPC" ,&RecoStartInTPC ,"RecoStartInTPC/B" );
228  fRecoTree->Branch("RecoEndInTPC" ,&RecoEndInTPC ,"RecoEndInTPC/B" );
229  fRecoTree->Branch("StartFromEdge" ,&StartFromEdge ,"StartFromEdge/D" );
230  fRecoTree->Branch("EndFromEdge" ,&EndFromEdge ,"EndFromEdge/D" );
231  fRecoTree->Branch("RecoContainment" ,&RecoContainment ,"RecoContainment/I" );
232  // Calorimetry objects
233  fRecoTree->Branch("CaloPlane0", &CaloPlane0, "CaloPlane0/I" );
234  fRecoTree->Branch("ResRPlane0", &ResRPlane0, "ResRPlane0[CaloPlane0]/D");
235  fRecoTree->Branch("dEdxPlane0", &dEdxPlane0, "dEdxPlane0[CaloPlane0]/D");
236  fRecoTree->Branch("CaloPlane1", &CaloPlane1, "CaloPlane1/I" );
237  fRecoTree->Branch("ResRPlane1", &ResRPlane1, "ResRPlane1[CaloPlane1]/D");
238  fRecoTree->Branch("dEdxPlane1", &dEdxPlane1, "dEdxPlane1[CaloPlane1]/D");
239  fRecoTree->Branch("CaloPlane2", &CaloPlane2, "CaloPlane2/I" );
240  fRecoTree->Branch("ResRPlane2", &ResRPlane2, "ResRPlane2[CaloPlane2]/D");
241  fRecoTree->Branch("dEdxPlane2", &dEdxPlane2, "dEdxPlane2[CaloPlane2]/D");
242 
243  // ==== My truth tree
244  fTrueTree = tfs->make<TTree>("TruthTree","truth_tree");
245  fTrueTree->Branch("True_Particles", &True_Particles, "True_Particles/I" );
246  fTrueTree->Branch("True_PdgCode" , &True_PdgCode , "True_PdgCode[True_Particles]/I" );
247  fTrueTree->Branch("True_ID" , &True_ID , "True_ID[True_Particles]/I" );
248  fTrueTree->Branch("True_Contained", &True_Contained, "True_Contained[True_Particles]/I" );
249  fTrueTree->Branch("True_Primary" , &True_Primary , "True_Primary[True_Particles]/I" );
250  fTrueTree->Branch("True_Length" , &True_Length , "True_Length[True_Particles]/D" );
251  fTrueTree->Branch("True_StartX" , &True_StartX , "True_StartX[True_Particles]/D" );
252  fTrueTree->Branch("True_StartY" , &True_StartY , "True_StartY[True_Particles]/D" );
253  fTrueTree->Branch("True_StartZ" , &True_StartZ , "True_StartZ[True_Particles]/D" );
254  fTrueTree->Branch("True_EndX" , &True_EndX , "True_EndX[True_Particles]/D" );
255  fTrueTree->Branch("True_EndY" , &True_EndY , "True_EndY[True_Particles]/D" );
256  fTrueTree->Branch("True_EndZ" , &True_EndZ , "True_EndZ[True_Particles]/D" );
257 }
258 // ************************************ End Job *********************************************************
260  std::cout << "\nFinished all the events for module " << fTrackModuleLabel << "..."
261  << "\nMonte Carlo's in the TPC had a total of " << TrueMuons << " Muons, " << TrueProtons << " Protons, " << TrueElectrons << " Electrons, " << TrueGammas << " Gammas, and " << TrueOthers << " others."
262  << "\nHad a total of " << AllAll << " tracks. Comprised of Muons " << MuonAll << ", Protons " << ProtonAll << ", Gammas " << GammaAll << ", Electrons " << ElectronBad << ", Others " << OtherAll
263  << "\n" << AllBad << " of which had high PIDA's, Muons " << MuonBad << ", Protons " << ProtonBad << ", Gammas " << GammaBad << ", Electrons " << ElectronBad << ", Others " << OtherBad
264  << "\n" << AllRange << " tracks were within PIDA range, Muons " << MuonRange << ", Protons " << ProtonRange << ", Gammas " << GammaRange << ", ElectronRange " << ElectronRange << ", Others " << OtherRange
265  << std::endl;
266 }
267 // ************************************ End Run *********************************************************
269 }
270 
271 // ********************************** pset param *******************************************************
273  : EDAnalyzer(pset)
274  , fHitsModuleLabel ( pset.get< std::string >("HitsModuleLabel"))
275  , fTrackModuleLabel ( pset.get< std::string >("TrackModuleLabel"))
276  , fMCTruthT0ModuleLabel ( pset.get< std::string >("MCTruthT0ModuleLabel"))
277  , fPhotonT0ModuleLabel ( pset.get< std::string >("PhotonT0ModuleLabel"))
278  , fCounterT0ModuleLabel ( pset.get< std::string >("CounterT0ModuleLabel"))
279  , fCalorimetryModuleLabel ( pset.get< std::string >("CalorimetryModuleLabel"))
280  , fUsePhotons ( pset.get< bool >("UsePhotons"))
281  , PIDApower ( pset.get< double >("PIDApower"))
282  , fBoundaryEdge ( pset.get< double >("BoundaryEdge"))
283  , Verbose ( pset.get< int >("Verbose"))
284 {
285  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataForJob();
286  auto const detProp = art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataForJob(clockData);
287  XDriftVelocity = detProp.DriftVelocity()*1e-3; //cm/ns
288  WindowSize = detProp.NumberTimeSamples() * clockData.TPCClock().TickPeriod() * 1e3;
289 }
290 // ******************************************************************************************************
292 {
293  // Clean up dynamic memory and other resources here.
294 
295 }
296 // ************************************ Analyse *********************************************************
298 {
299  //std::cout << "\n\n************* New Event / Module running *************\n\n" << std::endl;
300  // Implementation of required member function here.
301  std::vector<art::Ptr<recob::Track> > tracklist;
302  auto trackListHandle = evt.getHandle< std::vector<recob::Track> >(fTrackModuleLabel);
303  if (trackListHandle)
304  art::fill_ptr_vector(tracklist, trackListHandle);
305 
306  auto trackh = evt.getHandle< std::vector<recob::Track> >(fTrackModuleLabel);
307 
308  std::vector<art::Ptr<raw::ExternalTrigger> > triglist;
309  auto trigListHandle = evt.getHandle< std::vector<raw::ExternalTrigger> >(fCounterT0ModuleLabel);
310  if (trigListHandle)
311  art::fill_ptr_vector(triglist, trigListHandle);
312 
313  const sim::ParticleList& plist = pi_serv->ParticleList();
314  True_Particles = 0;
315  for (int qq=0; qq<1000; ++qq) {
316  True_PdgCode [ qq ] = True_Contained[ qq ] = True_Length [ qq ] = True_ID[qq] = True_Primary[qq] = 0;
317  True_StartX [ qq ] = True_StartY [ qq ] = True_StartZ [ qq ] = 0;
318  True_EndX [ qq ] = True_EndY [ qq ] = True_EndZ [ qq ] = 0;
319  }
320 // Quickly get total number of MC Particles...
321  for ( sim::ParticleList::const_iterator ipar = plist.begin(); ipar!=plist.end(); ++ipar){
322  // Some variables by each particle
323  bool InTPC = false, StIn = false, EnIn = false;
324  double ThisStX=0, ThisStY=0, ThisStZ=0, ThisEnX=0, ThisEnY=0, ThisEnZ=0;
325  double ThisLen=0;
326  int ThisPDG=0, ThisCon=-1, ThisID=-1, ThisPri=-1;
327  // Get my particle and loop through points
328  simb::MCParticle *particle = ipar->second;
329  ThisPDG = particle->PdgCode();
330  ThisID = particle->TrackId();
331  if (particle->Process() == "primary") ThisPri=1;
332  else ThisPri=0;
333  for ( unsigned int a=0; a<particle->NumberTrajectoryPoints(); ++a ) {
334  // Get Positions and if in TPC
335  const TLorentzVector& tmpPosition=particle->Position(a);
336  double const tmpPosArray[]={tmpPosition[0],tmpPosition[1],tmpPosition[2]};
337  geo::TPCID tpcid = geom->FindTPCAtPosition(tmpPosArray);
338  if (tpcid.isValid && a == 0)
339  StIn = true;
340  if (tpcid.isValid && a == (particle->NumberTrajectoryPoints() -1) )
341  EnIn = true;
342  // If not in TPC yet...
343  if (!InTPC) {
344  if (tpcid.isValid) {
345  InTPC = true;
346  ThisStX = tmpPosArray[0];
347  ThisStY = tmpPosArray[1];
348  ThisStZ = tmpPosArray[2];
349  // Increment some total output variables....
350  if (abs(particle->PdgCode()) == 13 ) ++TrueMuons;
351  else if (abs(particle->PdgCode()) == 11 ) ++TrueElectrons;
352  else if (abs(particle->PdgCode()) == 22 ) ++TrueGammas;
353  else if (abs(particle->PdgCode()) == 2212 ) ++TrueProtons;
354  else ++TrueOthers;
355  } // First time in TPC
356  } else {
357  // If already been in TPC
358  if (tpcid.isValid) {
359  // And still in the TPC!
360  ThisEnX = tmpPosArray[0];
361  ThisEnY = tmpPosArray[1];
362  ThisEnZ = tmpPosArray[2];
363  } // Still in TPC
364  } // Already in TPC
365  } // Traj points
366  if(!StIn && !EnIn ) ThisCon = 0; // through track
367  if(!StIn && EnIn ) ThisCon = 1; // entering track
368  if( StIn && !EnIn ) ThisCon = 2; // escaping track
369  if( StIn && EnIn ) ThisCon = 3; // contained track
370  ThisLen = CalcDist( ThisStX, ThisStY, ThisStZ, ThisEnX, ThisEnY, ThisEnZ );
371  /*
372  std::cout << "Finished particle info...InTPC " << InTPC << " PDG " << ThisPDG
373  << ", start " << ThisStX << ", " << ThisStY << ", " << ThisStZ << "....End " << ThisEnX << ", " << ThisEnY << ", " << ThisEnZ
374  << "....StIn " << StIn << ", EnIn " << EnIn << ", ThisCon " << ThisCon << ", Len " << ThisLen
375  << std::endl;
376  */
377  if (InTPC && True_Particles < 1000) {
378  True_PdgCode [ True_Particles ] = ThisPDG;
379  True_ID [ True_Particles ] = ThisID;
380  True_Contained[ True_Particles ] = ThisCon;
381  True_Primary [ True_Particles ] = ThisPri;
382  True_Length [ True_Particles ] = ThisLen;
383  True_StartX [ True_Particles ] = ThisStX;
384  True_StartY [ True_Particles ] = ThisStY;
385  True_StartZ [ True_Particles ] = ThisStZ;
386  True_EndX [ True_Particles ] = ThisEnX;
387  True_EndY [ True_Particles ] = ThisEnY;
388  True_EndZ [ True_Particles ] = ThisEnZ;
389  ++True_Particles;
390  }
391  } // Particle list
392  // Now I have gone through particle list fill the tree.
393  fTrueTree -> Fill();
394 
395  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(evt);
396  auto const detProp = art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(evt, clockData);
397  if ( trackListHandle.isValid() ) { // Check that trackListHandle is valid.....
398  art::FindManyP<recob::Hit> fmht (trackListHandle, evt, fTrackModuleLabel);
399  art::FindMany<anab::T0> fmt0 (trackListHandle, evt, fMCTruthT0ModuleLabel);
400  art::FindMany<anab::T0> fmphot (trackListHandle, evt, fPhotonT0ModuleLabel);
401  art::FindMany<anab::Calorimetry> fmcal (trackListHandle, evt, fCalorimetryModuleLabel);
402  int ntracks_reco=tracklist.size();
403 
404  for(int Track=0; Track < ntracks_reco; ++Track){
405  ResetVars(); // Reset variables.
406  std::cout << "\n***** Looking at new track " << Track << " of " << ntracks_reco << ", event " << evt.event() << ", Module " << fTrackModuleLabel << std::endl;
407 
408  // Load the new track info, and the basic track properties.
409  art::Ptr<recob::Track> ptrack(trackh, Track);
410  const recob::Track& track = *ptrack;
411  TrackLength = track.Length();
412  unsigned int NumTraj = track.NumberTrajectoryPoints();
413  // ---- Get lengths and angles.
414  if (NumTraj < 2) continue;
415  else {
416  TVector3 dir = track.VertexDirection<TVector3>();
417  TrackTheta_XZ = std::atan2(dir.X(), dir.Z());
418  TrackTheta_YZ = std::atan2(dir.Y(), dir.Z());
419  TrackEta_XY = std::atan2(dir.X(), dir.Y());
420  TrackEta_ZY = std::atan2(dir.Z(), dir.Y());
421  TrackTheta = dir.Theta();
422  TrackPhi = dir.Phi();
423  }
424  // ----- Hit Stuff ------
425  std::vector< art::Ptr<recob::Hit> > allHits = fmht.at(Track);
426  int NumHits = allHits.size();
427  for (int hit=0; hit<NumHits; ++hit) {
428  // The recob::Hit -> View() is backwards...
429  if ( allHits[hit]->View() == 2 ) ++TrackHits[0];
430  if ( allHits[hit]->View() == 1 ) ++TrackHits[1];
431  if ( allHits[hit]->View() == 0 ) ++TrackHits[2];
432  }
433  std::cout << "There were " << TrackHits[0] << ", " << TrackHits[1] << ", " << TrackHits[2] << " one each plane. " << std::endl;
434 
435  // *****************************************************************************
436  // T0 stuff - So can correct X Start/End positions and identify MCParticle!!
437  // *****************************************************************************
438  double TickT0 = -1.;
439  if ( fmt0.isValid() ) {
440  std::vector<const anab::T0*> T0s = fmt0.at(Track);
441  for (size_t t0size =0; t0size < T0s.size(); t0size++) {
442  MCTruthT0 = T0s[t0size]->Time();
443  MCTruthTickT0 = MCTruthT0 / sampling_rate(clockData);
444  MCTruthTrackID = T0s[t0size]->TriggerBits();
445  } // T0 size
446  TickT0 = MCTruthTickT0;
447  } // T0 valid
448  // ========== Rework out the MCTruth TrackID...Want to see if negative TrackID...
449  std::cout << "\n\nWorking out this TrackID" << std::endl;
450  std::map<int,double> trkide;
451  for(size_t h = 0; h < allHits.size(); ++h){
452  art::Ptr<recob::Hit> hit = allHits[h];
453  std::vector<sim::IDE> ides;
454  std::vector<sim::TrackIDE> TrackIDs = bt_serv->HitToTrackIDEs(clockData, hit);
455  for(size_t e = 0; e < TrackIDs.size(); ++e){
456  trkide[TrackIDs[e].trackID] += TrackIDs[e].energy;
457  }
458  }
459  double maxe = -1, tote = 0;
460  int TrackID = -1;
461  for (std::map<int,double>::iterator ii = trkide.begin(); ii!=trkide.end(); ++ii){
462  tote += ii->second;
463  if ((ii->second)>maxe){
464  maxe = ii->second;
465  TrackID = ii->first;
466  std::cout << "Highest E track was " << TrackID << ", deposited " << maxe << std::endl;
467  }
468  }
469  std::cout << "Old Best track was " << MCTruthTrackID << ", New Best track is " << TrackID << std::endl;
470  if ( fabs(MCTruthTrackID) != fabs(TrackID) ) std::cout << "!!!!!I HAVE A TOTALLY DIFFERENT TRACK!!!!!!\n" << std::endl;
471  else if ( MCTruthTrackID != TrackID ) std::cout << "The TrackIDs are different signs.\n" << std::endl;
472  else std::cout << "The TrackIDs are the same.\n" << std::endl;
473  MCTruthTrackID = TrackID;
474  std::cout << "The MCTruthTrackID is now " << MCTruthTrackID << std::endl;
475  // ========== Rework out the MCTruth TrackID...Want to see if negative TrackID...
476 
477  // If using photon detectors...
478  if ( fmphot.isValid() && fUsePhotons) {
479  std::vector<const anab::T0*> PhotT0 = fmphot.at(Track);
480  for (size_t T0it=0; T0it<PhotT0.size(); ++T0it) {
481  PhotonCounterT0 = PhotT0[T0it]->Time();
482  PhotonCounterTickT0 = PhotonCounterT0 / sampling_rate(clockData);
483  PhotonCounterID = PhotT0[T0it]->TriggerBits();
484  }
485  TickT0 = PhotonCounterTickT0;
486  }
487  // ************** END T0 stuff ***************
488 
489  if (TickT0 == -1.) continue;
490  double XCorFac = detProp.ConvertTicksToX( TickT0, 0, 0, 0 );
491  std::cout << "The TickT0 is " << TickT0 << ", giving an x correction to each hit of around " << XCorFac << std::endl;
492  // ******************************************************************************************
493  // Correct X and get track length etc now that we have matched a Track with an MCParticle!!
494  // ******************************************************************************************
495 
496  // ---- Correct X positions!
497  std::vector < TVector3 > CorrectedLocations;
498  CorrectedLocations.clear();
499  for ( unsigned int point=0; point < NumTraj; ++point ) {
500  const TVector3 ThisLoc = track.LocationAtPoint<TVector3>(point);
501  TVector3 CorrectLoc = ThisLoc;
502  CorrectLoc[0] = CorrectLoc[0] - detProp.ConvertTicksToX( TickT0, allHits[NumTraj-(1+point)]->WireID().Plane, allHits[NumTraj-(1+point)]->WireID().TPC, allHits[NumTraj-(1+point)]->WireID().Cryostat );
503  CorrectedLocations.push_back(CorrectLoc);
504  }
505  CorrectedStartX = CorrectedLocations[0][0];
506  CorrectedStartY = CorrectedLocations[0][1];
507  CorrectedStartZ = CorrectedLocations[0][2];
508  CorrectedEndX = CorrectedLocations[NumTraj-1][0];
509  CorrectedEndY = CorrectedLocations[NumTraj-1][1];
510  CorrectedEndZ = CorrectedLocations[NumTraj-1][2];
511 
512  // **************************************************************
513  // Determine what kind of particle actually caused the track.....
514 
515  int ii = 0;
516  for ( sim::ParticleList::const_iterator ipar = plist.begin(); ipar!=plist.end(); ++ipar){
517  simb::MCParticle *MyParticle = ipar->second;
518  ++ii;
519  if ( MyParticle->TrackId() != fabs(MCTruthTrackID) )
520  continue;
521  MatchedTrackID = Track;
522  // ---- Get MCTruth Information and check that MCParticle goes in TPC ---
523  MCTruthInformation ( clockData, MyParticle );
524 
525  // Work out if the track is back to front...
526  // MC Start -> Track
527  double St_St = CalcDist( MCStartX, MCStartY, MCStartZ, CorrectedStartX, CorrectedStartY, CorrectedStartZ );
528  double St_En = CalcDist( MCStartX, MCStartY, MCStartZ, CorrectedEndX , CorrectedEndY , CorrectedEndZ );
529  // MC End -> Track
530  double En_St = CalcDist( MCEndX , MCEndY , MCEndZ , CorrectedStartX, CorrectedStartY, CorrectedStartZ );
531  double En_En = CalcDist( MCEndX , MCEndY , MCEndZ , CorrectedEndX , CorrectedEndY , CorrectedEndZ );
532 
533  // If backwards...
534  if ( (St_En < St_St) && (En_St < En_En) ) {
535  std::cout << "I think that this track is backwards." << std::endl;
536  } else {
537  MCCorOrient = true;
538  }
539  if (Verbose) {
540  std::cout <<"MC Start ("<< MCStartX << ", " << MCStartY << ", " << MCStartZ << ")\n"
541  << "Reco Start ("<< CorrectedStartX << ", " << CorrectedStartY << ", " << CorrectedStartZ << ")\n"
542  << "MC End ("<< MCEndX << ", " << MCEndY << ", " << MCEndZ << ")\n"
543  << "Reco End ("<< CorrectedEndX << ", " << CorrectedEndY << ", " << CorrectedEndZ << ")\n"
544  << "Dist of MC Start to Track Start/End is " << St_St << ", " << St_En << "\n"
545  << "Dist of MC End to Track Start/End is " << En_St << ", " << En_En << "\n";
546  if (!MCCorOrient)
547  std::cout << "The track is the wrong way around...Will need to correct later.\n";
548  }
549  break;
550  } // Check what particle caused this track....
551  // ****************************************************************
552 
553  ++AllAll;
554  if (fabs(MCPdgCode) == 13 ) ++MuonAll;
555  else if (fabs(MCPdgCode) == 11 ) ++ElectronAll;
556  else if (MCPdgCode == 2212 ) ++ProtonAll;
557  else if (MCPdgCode == 22 ) ++GammaAll;
558  else ++OtherAll;
559 
560  // Want to select only tracks which stop in the detector.
561  TrackBoundaries( CorrectedLocations[0], CorrectedLocations[NumTraj-1] );
562  //if ( RecoContainment == 0 || RecoContainment == 2 ) continue;
563 
564  // ---- Make a vector of calorimetry objects...
565  std::vector<const anab::Calorimetry*> calos = fmcal.at(Track);
566  PIDA = CalcPIDA ( calos );
567 
568  // ************************************************************
569  // Now see what values of PIDA each particle type has
570  // ************************************************************
571  int QuickThresh = 25;
572  if (PIDA_Plane2 > QuickThresh ) {
573  std::cout << "\nTrack " << Track << " has a PIDA value of " << PIDA << ", " << NumTraj << " traj points and " << NumHits << " hits, PdGCode " << MCPdgCode << " , MCTrackID " << MCTrackId << std::endl;
574  ++AllBad;
575  if (fabs(MCPdgCode) == 13 ) ++MuonBad;
576  else if (fabs(MCPdgCode) == 11) ++ElectronBad;
577  else if (MCPdgCode == 2212 ) ++ProtonBad;
578  else if (MCPdgCode == 22 ) ++GammaBad;
579  else ++OtherBad;
580  }
581  if (PIDA_Plane2 > 15 && PIDA_Plane2 < 25 && (RecoContainment == 1 || RecoContainment == 3) ) {
582  ++AllRange;
583  if (fabs(MCPdgCode) == 13 ) ++MuonRange;
584  else if (fabs(MCPdgCode) == 11) ++ElectronRange;
585  else if (MCPdgCode == 2212 ) ++ProtonRange;
586  else if (MCPdgCode == 22 ) ++GammaRange;
587  else ++OtherRange;
588  }
589  // ******** Fill Tree for each MCParticle **********
590  fRecoTree->Fill();
591 
592  // Write some output so I can check how particles do when subject to my macro cuts....
593  std::cout << "\n==== When subject to macro cuts ===" << std::endl;
594  // What kind of particle is it?
595  if (fabs(MCPdgCode) == 13) std::cout << "This is a muon." << std::endl;
596  else if (fabs(MCPdgCode) == 2212) std::cout << "This is a proton." << std::endl;
597  else {
598  std::cout << "This is a " << MCPdgCode << ", not interested, so continuing." << std::endl;
599  continue;
600  }
601  // MC cont cuts
602  if (MCContainment == 0 || MCContainment == 2 ) std::cout << "Would get cut by MC cut on stopping particles." << std::endl;
603  else if (MCContainment == 1 ) std::cout << "Would get cut by MC cut on contained particles." << std::endl;
604  else if (MCContainment == 3 ) std::cout << "This is a fully contained track.." << std::endl;
605  // Reco cont cuts
606  if (RecoContainment == 0 || RecoContainment == 2 ) std::cout << "Would get cut by Reco cut on stopping particles." << std::endl;
607  else if (RecoContainment == 1 ) std::cout << "Would get cut by Reco cut on contained particles." << std::endl;
608  else if (RecoContainment == 3 ) std::cout << "This is a fully contained track." << std::endl;
609  // Unreasonably high PIDA value.
610  if (PIDA > 25) std::cout << "Unreasonably high PIDA of " << PIDA << ". ";
611  else std::cout << "Has a Reasonabe PIDA of " << PIDA << ". ";
612  if (PIDA_Plane2 > 25 ) std::cout << "Unreasonably high PIDA_Plane2 of " << PIDA_Plane2 << std::endl;
613  else std::cout << "Has a Reasonabe PIDA_Plane2 of " << PIDA_Plane2 << std::endl;
614  if (PIDA > 14 && PIDA < 18) std::cout << "Would lie in the proton PIDA area" << std::endl;
615  if (PIDA > 5 && PIDA < 9 ) std::cout << "Would lie in the muon PIDA area" << std::endl;
616  // Minimum number of coll plane hits
617  if (CaloPlane2 < 5) std::cout << "Has less than 5 collection plane hits." << std::endl;
618  else if (CaloPlane2 < 10) std::cout << "Has less than 10 collection plane hits." << std::endl;
619  else std::cout << "Has more than 10 collection plane hits " << CaloPlane2 << std::endl;
620  // Correct orientation
621  if (!MCCorOrient ) std::cout << "The track was the wrong way around!" << std::endl;
622  else std::cout << "The track was the right way around!" << std::endl;
623  // Missed end points...
624  if ( fabs( CorrectedEndX - MCEndX ) > 2.5 ) std::cout << "Missed the end point of the particle in X" << std::endl;
625  if ( fabs( CorrectedEndY - MCEndY ) > 2.5 ) std::cout << "Missed the end point of the particle in Y" << std::endl;
626  if ( fabs( CorrectedEndZ - MCEndZ ) > 2.5 ) std::cout << "Missed the end point of the particle in Z" << std::endl;
627  } // Loop over Tracks
628  } // if trackListHandle.isValid()
629 } // Analyse
630 
631 // ******************************** Calc PIDA ****************************************************
632 double ProtonIdentification::ProtonIdentification::CalcPIDA ( std::vector<const anab::Calorimetry*> calos ) {
633  double PIDA = 0, dEdxSum = 0;
634  int UsedHits = 0, TotHits = 0;
635 
636  // I need to decide which way to go through the hits...
637  double SumdEdx_St = 0., SumdEdx_En = 0., ResRng_St = 0, ResRng_En = 0;
638  unsigned int AvHits = 5;
639  if (calos[2]->dEdx().size()) {
640  ResRng_St = calos[2]->ResidualRange()[0];
641  ResRng_En = calos[2]->ResidualRange()[calos[2]->dEdx().size()-1];
642  }
643  // If don't have 2*AvHits (10) hits on the collection plane then use mid point + 1 hit
644  if ( calos[2]->dEdx().size() < (2*AvHits) ) {
645  AvHits = 1 + (0.5 * calos[2]->dEdx().size());
646  }
647  for ( unsigned int PlHit=0; PlHit < calos[2]->dEdx().size(); ++PlHit ) { // loop through hits on the collection plane
648  if ( PlHit <= AvHits ) {
649  SumdEdx_St += calos[2]->dEdx()[PlHit];
650  }
651  if ( calos[2]->dEdx().size() - PlHit <= AvHits ) {
652  SumdEdx_En += calos[2]->dEdx()[PlHit];
653  }
654  //std::cout << "Looking at hit " << PlHit << " of " << (int)calos[2]->dEdx().size() << "...SumdEdx_St = " << SumdEdx_St << ", and SumdEdx_En = " << SumdEdx_En << std::endl;
655  }
656  double AvdEdx_St = SumdEdx_St / AvHits;
657  double AvdEdx_En = SumdEdx_En / AvHits;
658  // The dEdx at the start of the track should be less than that at the end...
659  bool LowResSt = false;
660  if ( ResRng_St < ResRng_En )
661  LowResSt = true;
662  bool LowdEdxSt = false;
663  if ( AvdEdx_St < AvdEdx_En )
664  LowdEdxSt = true;
665 
666  if ( LowResSt && (!MCCorOrient) ) {
667  std::cout << "Track backwards, but calorimetry correct so setting everything to true...." << std::endl;
668  MCCorOrient = true;
669  double TmpX, TmpY, TmpZ;
670  TmpX = CorrectedStartX; TmpY = CorrectedStartY; TmpZ = CorrectedStartZ;
671  CorrectedStartX = CorrectedEndX ; CorrectedStartY = CorrectedEndY ; CorrectedStartZ = CorrectedEndZ ;
672  CorrectedEndX = TmpX ; CorrectedEndY = TmpY ; CorrectedEndZ = TmpZ ;
673  std::cout << "Reco Start ("<< CorrectedStartX << ", " << CorrectedStartY << ", " << CorrectedStartZ << ")\n"
674  << "Reco End ("<< CorrectedEndX << ", " << CorrectedEndY << ", " << CorrectedEndZ << ")\n";
675  }
676  std::cout << "AvdEdx_St is " << AvdEdx_St << ", and AvdEdx_En is " << AvdEdx_En << "....ResRng_St is " << ResRng_St << ", and ResRng_En is " << ResRng_En
677  << " ====>>> LowResSt " << LowResSt << ", LowdEdxSt " << LowdEdxSt << ", and TruthOrient? " << MCCorOrient << std::endl;
678 
679  if ( !MCCorOrient ) {
680  std::cout << "This track is wrong?" << std::endl;
681  }
682 
683  // *********** How do I deal with backwards tracks....What do I do if only one is backwards?.....
684  // If the dEdx is the wrong way around then without truth I would assume that the track is backwards.
685  // This means that I should use whether the MC is correct as a later cut.
686  // So if MCCorOrient == false then get PIDA using start of 'track'
687  for ( int Plane=0; Plane < (int)calos.size(); ++Plane ) { // Loop through planes
688  double PlanePIDA=0; int PlaneHits=0;
689  for ( int PlaneHit=0; PlaneHit < (int)calos[Plane]->dEdx().size(); ++PlaneHit ) { // loop through hits on each plane
690  double ThisdEdx = calos[Plane]->dEdx()[PlaneHit];
691  double ThisResR = calos[Plane]->ResidualRange()[PlaneHit];
692  // Increment TotHits and dEdx sum
693  dEdxSum += ThisdEdx;
694  ++TotHits;
695  // Fill the calorimetry objects
696  if (Plane==0 && CaloPlane0<kMaxHits) {
697  dEdxPlane0[CaloPlane0] = ThisdEdx;
698  ResRPlane0[CaloPlane0] = ThisResR;
699  ++CaloPlane0;
700  } else if (Plane==1 && CaloPlane1<kMaxHits) {
701  dEdxPlane1[CaloPlane1] = ThisdEdx;
702  ResRPlane1[CaloPlane1] = ThisResR;
703  ++CaloPlane1;
704  } else if (Plane==2 && CaloPlane2<kMaxHits) {
705  dEdxPlane2[CaloPlane2] = ThisdEdx;
706  ResRPlane2[CaloPlane2] = ThisResR;
707  ++CaloPlane2;
708  }
709  // Output some calorimetry information
710  /*
711  double ThisRang = calos[Plane]->Range();
712  double ThisKinE = calos[Plane]->KineticEnergy();
713  TVector3 ThisPos = calos[Plane]->XYZ()[PlaneHit];
714  std::cout << "Looking at hit " << PlaneHit << " of " << (int)calos[Plane]->dEdx().size() << "...dEdx is " << ThisdEdx << ", ResR is "
715  << ThisResR << ", this Range is " << ThisRang << ", TrackLength is " << TrackLength << ", KinE is " << ThisKinE
716  << ". This is pos is (" << ThisPos[0] << ", " << ThisPos[1] << ", " << ThisPos[2] << ")."
717  << std::endl;
718  //*/
719 
720  // ==== If MCCorOrient == true
721  // Work out PIDA if ResRange < 30 cm
722  if ( ThisResR < 30 ) { // Only want PIDA for last 30 cm
723  PlanePIDA += PIDAFunc( ThisdEdx, ThisResR );
724  ++PlaneHits;
725  } // If ResRange < 30 cm
726  // ===== This is where I need to do things...
727  } // Loop over hits on each plane
728  // Increment whole track PIDA.
729  PIDA += PlanePIDA;
730  UsedHits += PlaneHits;
731  // Work out PIDA for this plane
732  PlanePIDA = PlanePIDA/PlaneHits;
733  if (Plane == 0 ) PIDA_Plane0 = PlanePIDA;
734  else if (Plane == 1 ) PIDA_Plane1 = PlanePIDA;
735  else if (Plane == 2 ) PIDA_Plane2 = PlanePIDA;
736  } // Loop over planes
737 
738  if ( UsedHits ) // If had any hits, work out PIDA and calculate
739  PIDA = PIDA / UsedHits;
740  AvdEdx = dEdxSum / TotHits;
741  return PIDA;
742 } // CalcPIDA
743 
744 // ******************************** Track Boundaries ****************************************************
745 void ProtonIdentification::ProtonIdentification::TrackBoundaries ( TVector3 larStart, TVector3 larEnd ) {
746 
747  if (MCCorOrient == false) {
748  TVector3 larTemp = larStart;
749  larStart = larEnd;
750  larEnd = larTemp;
751  std::cout << "Swapping positions for reco containment. " << std::endl;
752  }
753  std::cout << "The track positions are (" << larStart[0] << ", " << larStart[1] << ", " << larStart[2] << ") ("<< larEnd[0] << ", " << larEnd[1] << ", " << larEnd[2] << ") and boundaries are "
754  << boundaries[0] << " -> " << boundaries[1] << ", " << boundaries[2] << " -> " << boundaries[3] << ", " <<boundaries[4] << " -> " << boundaries[5] << std::endl;
755 
756  double XStartDiff = std::min( fabs(boundaries[0]-larStart[0]), fabs(boundaries[1]-larStart[0]) );
757  double YStartDiff = std::min( fabs(boundaries[2]-larStart[1]), fabs(boundaries[3]-larStart[1]) );
758  double ZStartDiff = std::min( fabs(boundaries[4]-larStart[2]), fabs(boundaries[5]-larStart[2]) );
759  if ( larStart[0] < boundaries[0] || larStart[0] > boundaries[1] ) XStartDiff = -XStartDiff;
760  if ( larStart[1] < boundaries[2] || larStart[1] > boundaries[3] ) YStartDiff = -YStartDiff;
761  if ( larStart[2] < boundaries[4] || larStart[2] > boundaries[5] ) ZStartDiff = -ZStartDiff;
762  RecoStartInTPC = false;
763  if ( XStartDiff > fBoundaryEdge && XStartDiff > 0 &&
764  YStartDiff > fBoundaryEdge && YStartDiff > 0 &&
765  ZStartDiff > fBoundaryEdge && ZStartDiff > 0
766  ) {
767  RecoStartInTPC = true;
768  }
769  StartFromEdge = std::min( XStartDiff, std::min(YStartDiff,ZStartDiff) );
770 
771  double XEndDiff = std::min( fabs(boundaries[0]-larEnd[0]), fabs(boundaries[1]-larEnd[0]) );
772  double YEndDiff = std::min( fabs(boundaries[2]-larEnd[1]), fabs(boundaries[3]-larEnd[1]) );
773  double ZEndDiff = std::min( fabs(boundaries[4]-larEnd[2]), fabs(boundaries[5]-larEnd[2]) );
774  if ( larEnd[0] < boundaries[0] || larEnd[0] > boundaries[1] ) XEndDiff = -XEndDiff;
775  if ( larEnd[1] < boundaries[2] || larEnd[1] > boundaries[3] ) YEndDiff = -YEndDiff;
776  if ( larEnd[2] < boundaries[4] || larEnd[2] > boundaries[5] ) ZEndDiff = -ZEndDiff;
777  RecoEndInTPC = false;
778  if ( XEndDiff > fBoundaryEdge && XEndDiff > 0 &&
779  YEndDiff > fBoundaryEdge && YEndDiff > 0 &&
780  ZEndDiff > fBoundaryEdge && ZEndDiff > 0
781  ) {
782  RecoEndInTPC = true;
783  }
784  EndFromEdge = std::min( XEndDiff, std::min(YEndDiff,ZEndDiff) );
785 
786  // *** What to do if the track is reconstructed backwards though....
787  // *** Do I want to look into that here or elsewhere?
788 
789  if(!RecoStartInTPC && !RecoEndInTPC ) RecoContainment = 0; // Through track
790  if(!RecoStartInTPC && RecoEndInTPC ) RecoContainment = 1; // Entering track
791  if( RecoStartInTPC && !RecoEndInTPC ) RecoContainment = 2; // Escaping track
792  if( RecoStartInTPC && RecoEndInTPC ) RecoContainment = 3; // Contained track
793  // If the timing is totally off...
794  if( XStartDiff < 0 || XEndDiff < 0 ) {
795  std::cout << "This particle was outside active vol...." << std::endl;
796  if ( std::max( fabs(larStart[1]-MCStartY), fabs(larStart[2]-MCStartZ ) ) < 5 &&
797  std::max( fabs(larEnd[1] -MCEndY) , fabs(larEnd[2] -MCEndZ ) ) < 5
798  ) {
799  std::cout << "But the Y and Z difference are small, so changing to MCContainment" << std::endl;
800  RecoContainment = MCContainment;
801  }
802  }
803 
804  std::cout << "RecoStartInTPC? " << RecoStartInTPC << ", RecoEndInTPC? " << RecoEndInTPC
805  << ", StartFromEdge " << StartFromEdge << ", EndFromEdge " << EndFromEdge
806  << ", RecoContainment " << RecoContainment << ", MCContainment " << MCContainment
807  << std::endl;
808 } // TrackBoundaries
809 // *********************************** Monte Carlo Truth Extraction ********************************************************
811  const simb::MCParticle *particle ) {
812  unsigned int numberTrajectoryPoints = particle->NumberTrajectoryPoints(); // Looking at each MC hit
813  //double TPCLengthHits[numberTrajectoryPoints];
814  //double TPCEnDepos [numberTrajectoryPoints];
815  std::vector<double> TPCLengthHits(numberTrajectoryPoints, 0);
816  std::vector<double> TPCEnDepos(numberTrajectoryPoints, 0);
817  bool BeenInVolume = false;
818  int FirstHit=0, LastHit=0;
819 
820  for(unsigned int MCHit=0; MCHit < TPCLengthHits.size(); ++MCHit) {
821  const TLorentzVector& tmpPosition=particle->Position(MCHit);
822  double const tmpPosArray[]={tmpPosition[0],tmpPosition[1],tmpPosition[2]};
823 
824  if (MCHit!=0) {
825  TPCLengthHits[MCHit] = pow ( pow( (particle->Vx(MCHit-1)-particle->Vx(MCHit)),2)
826  + pow( (particle->Vy(MCHit-1)-particle->Vy(MCHit)),2)
827  + pow( (particle->Vz(MCHit-1)-particle->Vz(MCHit)),2)
828  , 0.5 );
829  TPCEnDepos[MCHit] = 1000 * (particle->E(MCHit-1) - particle->E(MCHit));
830  }
831  // --- Check if hit is in TPC...
832  geo::TPCID tpcid = geom->FindTPCAtPosition(tmpPosArray);
833  if (tpcid.isValid) {
834  if (MCHit == 0 ) MCStartInTPC = true;
835  if (MCHit == numberTrajectoryPoints-1 ) MCEndInTPC = true;
836  // -- Check if hit is within drift window...
837  geo::CryostatGeo const& cryo = geom->Cryostat(tpcid.Cryostat);
838  geo::TPCGeo const& tpc = cryo.TPC(tpcid.TPC);
839  double XPlanePosition = tpc.PlaneLocation(0)[0];
840  double DriftTimeCorrection = fabs( tmpPosition[0] - XPlanePosition ) / XDriftVelocity;
841  double TimeAtPlane = particle->T() + DriftTimeCorrection;
842  if ( TimeAtPlane < trigger_offset(clockData)
843  || TimeAtPlane > trigger_offset(clockData) + WindowSize
844  ) continue;
845  // -- Good hit in TPC
846  LastHit = MCHit;
847  MCEndX = particle->Vx(MCHit) ; MCEndY = particle->Vy(MCHit) ; MCEndZ = particle->Vz(MCHit);
848  if ( !BeenInVolume ) {
849  BeenInVolume = true;
850  FirstHit = MCHit;
851  MCStartX = particle->Vx(MCHit) ; MCStartY = particle->Vy(MCHit) ; MCStartZ = particle->Vz(MCHit);
852  }
853  } // TPC.valid
854  } // MCTrajPoints
855  // What is the true containment?
856  if(!MCStartInTPC && !MCEndInTPC ) MCContainment = 0; // through track
857  if(!MCStartInTPC && MCEndInTPC ) MCContainment = 1; // entering track
858  if( MCStartInTPC && !MCEndInTPC ) MCContainment = 2; // escaping track
859  if( MCStartInTPC && MCEndInTPC ) MCContainment = 3; // contained track
860  std::cout << "This track is from a " << particle->PdgCode() <<", StartInTPC? " << MCStartInTPC << ", EndInTPC? " << MCEndInTPC << ", MCContainment " << MCContainment << std::endl;
861 
862  // Work out the energy deposited etc.
863  MCEnergy = particle->E(FirstHit);
864  MCEnergyDeposited = particle->E(FirstHit) - particle->E(LastHit);
865  for (int Hit = FirstHit+1; Hit <= LastHit; ++Hit ) {
866  MCTPCLength += TPCLengthHits[Hit];
867  }
868  // ********* Need to work out MC PIDA *********
869  // I think I want to do this using SimChannels..
870  double SumPIDA = 0;
871  int MCHits = 0;
872  double NewDist = 0;
873  for (int Hit = FirstHit+1; Hit <= LastHit; ++Hit ) {
874  NewDist += TPCLengthHits[Hit];
875  double ThdEdx = TPCEnDepos[Hit] / TPCLengthHits[Hit];
876  double ThResR = MCTPCLength - NewDist;
877  // If no dEdx then can't add to PIDA value
878  if (TPCEnDepos[Hit] == 0) continue;
879  double ThPIDA = PIDAFunc( ThdEdx, ThResR );
880  if ( ThResR < 30 ) {
881  SumPIDA += ThPIDA;
882  ++MCHits;
883  }
884  if (Verbose > 1) {
885  std::cout << "Looking at Hit " << Hit << " to " << LastHit << ". Total length was " << MCTPCLength << ", now gone " << NewDist << ". "
886  << "dEdx here was " << ThdEdx << ", ResRange was " << ThResR << ", so PIDA = " << ThPIDA << " = " << ThdEdx << " * " << ThResR << "^"<<PIDApower<< ".\n"
887  << "The PIDA sum is now " << SumPIDA << ", and I have used " << MCHits << " hits."
888  << std::endl;
889  }
890  }
891  MCPIDA = SumPIDA / MCHits;
892  std::cout << "The MCPIDA is " << MCPIDA << std::endl;
893 
894  // Set the MC parameters for the track
895  MCPdgCode = particle->PdgCode();
896  MCTrackId = particle->TrackId();
897  if (particle->Process() == "primary") {
898  MCIsPrimary = 1;
899  if (MCTruthTrackID < 0)
900  MCIsPrimary = -1;
901  } else
902  MCIsPrimary = 0;
903  std::cout << "What kind of primary identifier? " << MCIsPrimary << std::endl;
904  TLorentzVector& momentumStart = (TLorentzVector&)particle->Momentum(FirstHit);
905  TVector3 mcstartmom = particle->Momentum(FirstHit).Vect();
906  MCTheta_XZ = std::atan2(momentumStart.Px(), momentumStart.Pz());
907  MCTheta_YZ = std::atan2(momentumStart.Py(), momentumStart.Pz());
908  MCEta_XY = std::atan2(momentumStart.Px(), momentumStart.Py());
909  MCEta_ZY = std::atan2(momentumStart.Pz(), momentumStart.Py());
910  MCTheta = mcstartmom.Theta();
911  MCPhi = mcstartmom.Phi();
912 
913  return;
914 } // MCTruthInformation
915 // ******************************** Calc the dists ******************************************************
916 double ProtonIdentification::ProtonIdentification::CalcDist( double X1, double Y1, double Z1, double X2, double Y2, double Z2 ) {
917  double Sq = TMath::Power( X1-X2 , 2 ) + TMath::Power( Y1-Y2 , 2 ) + TMath::Power( Z1-Z2 , 2 );
918  double Va = TMath::Power( Sq, 0.5 );
919  return Va;
920 } // Calc the dists
921 // ******************************** PIDA func ******************************************************
922 double ProtonIdentification::ProtonIdentification::PIDAFunc( double dedx, double resrng ) {
923  double Va = dedx * pow( resrng, PIDApower );
924  return Va;
925 }
926 // ******************************** Reset Variables *****************************************************
928  // MC info
929  MCTPCLength = MCEnergy = MCEnergyDeposited = MCPIDA = 0;
930  MCPdgCode = MCTrackId = MatchedTrackID = MCContainment = 0;
931  MCStartX = MCStartY = MCStartZ = MCEndX = MCEndY = MCEndZ = 0;
932  // Reco info
933  PIDA = PIDA_Plane0 = PIDA_Plane1 = PIDA_Plane2 = StartFromEdge = EndFromEdge = TrackLength = 0;
934  CorrectedStartX = CorrectedStartY = CorrectedStartZ = CorrectedEndX = CorrectedEndY = CorrectedEndZ = 0;
935  TrackHits[0] = TrackHits[1] = TrackHits[2] = RecoContainment = 0;
936  // Booleans
937  MCStartInTPC = MCEndInTPC = RecoStartInTPC = RecoEndInTPC = false;
938  MCCorOrient = false;
939  // Calorimetry
940  CaloPlane0 = CaloPlane1 = CaloPlane2 = 0;
941  for (int ii=0; ii<kMaxHits; ++ii) {
942  ResRPlane0[ii] = ResRPlane1[ii] = ResRPlane2[ii] = 0;
943  dEdxPlane0[ii] = dEdxPlane1[ii] = dEdxPlane2[ii] = 0;
944  }
945 }
946 // ******************************** Define Module *****************************************************
double E(const int i=0) const
Definition: MCParticle.h:233
intermediate_table::iterator iterator
unsigned int NumberTrajectoryPoints() const
Definition: MCParticle.h:218
const TLorentzVector & Position(const int i=0) const
Definition: MCParticle.h:219
int PdgCode() const
Definition: MCParticle.h:212
EventNumber_t event() const
Definition: DataViewImpl.cc:85
Encapsulate the construction of a single cyostat.
double CalcPIDA(std::vector< const anab::Calorimetry * > calos)
art::ServiceHandle< cheat::ParticleInventoryService > pi_serv
AdcChannelData::View View
Handle< PROD > getHandle(SelectorBase const &) const
Definition: DataViewImpl.h:382
std::string string
Definition: nybbler.cc:12
std::vector< TrackID > TrackIDs
void MCTruthInformation(detinfo::DetectorClocksData const &clockData, const simb::MCParticle *particle)
Point_t const & LocationAtPoint(size_t i) const
Definition: Track.h:126
constexpr T pow(T x)
Definition: pow.h:72
bool isValid
Whether this ID points to a valid element.
Definition: geo_types.h:211
Geometry information for a single TPC.
Definition: TPCGeo.h:38
size_t NumberTrajectoryPoints() const
Various functions related to the presence and the number of (valid) points.
Definition: Track.h:102
Vector_t VertexDirection() const
Definition: Track.h:132
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:212
STL namespace.
intermediate_table::const_iterator const_iterator
string dir
Geometry information for a single cryostat.
Definition: CryostatGeo.h:43
EDAnalyzer(fhicl::ParameterSet const &pset)
Definition: EDAnalyzer.h:25
std::string Process() const
Definition: MCParticle.h:215
Particle class.
art framework interface to geometry description
Definition: Run.h:17
int TrackId() const
Definition: MCParticle.h:210
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
T abs(T value)
double dEdx(float dqdx, float Efield)
Definition: doAna.cpp:21
const int kMaxHits
const double e
double Length(size_t p=0) const
Access to various track properties.
Definition: Track.h:167
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:67
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
IteratorBox< TPC_iterator,&GeometryCore::begin_TPC,&GeometryCore::end_TPC > IterateTPCs() const
Enables ranged-for loops on all TPCs of the detector.
const double a
double T(const int i=0) const
Definition: MCParticle.h:224
p
Definition: test.py:223
static int max(int a, int b)
The data type to uniquely identify a TPC.
Definition: geo_types.h:386
Detector simulation of raw signals on wires.
Encapsulate the geometry of a wire.
double Vx(const int i=0) const
Definition: MCParticle.h:221
Declaration of signal hit object.
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
Encapsulate the construction of a single detector plane.
Contains all timing reference information for the detector.
const TPCGeo & TPC(unsigned int itpc) const
Return the itpc&#39;th TPC in the cryostat.
Definition: CryostatGeo.cxx:93
art::ServiceHandle< cheat::BackTrackerService > bt_serv
double CalcDist(double X1, double Y1, double Z1, double X2, double Y2, double Z2)
const TLorentzVector & Momentum(const int i=0) const
Definition: MCParticle.h:220
def center(depos, point)
Definition: depos.py:117
Provides recob::Track data product.
double Vz(const int i=0) const
Definition: MCParticle.h:223
int trigger_offset(DetectorClocksData const &data)
TrackCollectionProxyElement< TrackCollProxy > Track
Proxy to an element of a proxy collection of recob::Track objects.
Definition: Track.h:1036
TCEvent evt
Definition: DataStructs.cxx:7
auto const & get(AssnsNode< L, R, D > const &r)
Definition: AssnsNode.h:115
void fill_ptr_vector(std::vector< Ptr< T >> &ptrs, H const &h)
Definition: Ptr.h:297
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:406
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
recob::tracking::Plane Plane
Definition: TrackState.h:17
void TrackBoundaries(TVector3 larStart, TVector3 larEnd)
int bool
Definition: qglobal.h:345
const double * PlaneLocation(unsigned int p) const
Definition: TPCGeo.cxx:382
double Vy(const int i=0) const
Definition: MCParticle.h:222
Track from a non-cascading particle.A recob::Track consists of a recob::TrackTrajectory, plus additional members relevant for a "fitted" track:
Definition: Track.h:49
constexpr Point origin()
Returns a origin position with a point of the specified type.
Definition: geo_vectors.h:227
QTextStream & endl(QTextStream &s)
Encapsulate the construction of a single detector plane.