EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
EicRcParticle.h
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file EicRcParticle.h
1 //
2 // AYK (ayk@bnl.gov), 2014/07/08
3 //
4 // EIC reconstructed particle class; interface to eic-smear,
5 // PANDA classes (like MCTrack and PidChargedCand) is conveniently
6 // hidden from end user;
7 //
8 
9 #include <TVector3.h>
10 #include <TParticlePDG.h>
11 
12 #include <PndMCTrack.h>
13 
15 
16 #include <TClonesArray.h>
17 class PndPidCandidate;
18 //class EicRcVertex;
19 
20 #ifndef _EIC_RC_PARTICLE_
21 #define _EIC_RC_PARTICLE_
22 
24  friend class EicEventAssembler;
25  friend class EicRcParticle;
26 
27  public:
30 
31  private:
32  Double_t mEnergy; // reconstructed hit energy ...
33  Double_t mEnergySigma; // ... with estimated uncertainty
34  TVector3 mLocation; // 3D location of this hit
35  // NB: cluster arrays are detector-specific (say, mBemcClusters in EventAssembler);
36  //std::vector<unsigned> mCellGroupIDs; // cell group IDs of clusters which were used to estimate energy & location
37 
39 };
40 
42  // No reason to have excessive Set...() methods;
43  friend class EicEventAssembler;
44 
45  public:
49  { mEmCal = mHCal = 0; };
51 
52  // ------------- erhic::VirtualParticle (pure) virtual method implementation
53 
54  // Well, the original eic-smear writers were aware about TVector3 class
55  // existence, right?; so what was the point of introducing this stuff?;
56  // tried to save some CPU time perhaps ...;
57  virtual Double_t GetPx() const { return mRcVtxMomentum.Px(); };
58  virtual Double_t GetPy() const { return mRcVtxMomentum.Py(); };
59  virtual Double_t GetPz() const { return mRcVtxMomentum.Pz(); };
60  virtual Double_t GetP() const { return mRcVtxMomentum.Mag(); };
61  virtual Double_t GetPt() const { return mRcVtxMomentum.Pt(); };
62  virtual Double_t GetTheta() const { return mRcVtxMomentum.Theta(); };
63  virtual Double_t GetPhi() const { return mRcVtxMomentum.Phi(); };
64  // "True" rapidity;
65  virtual Double_t GetRapidity() const;
66  // Pseudorapidity;
67  virtual Double_t GetEta() const;
68  // Interaction vertex for primary particles; decay vertex for secondary ones;
69  virtual TVector3 GetVertex() const { return mRcVertex; };
70 
71  // FIXME: check with eic-smear codes later which implementation is expected;
72  void SetVertex(const TVector3&) { exit(0); };
73 
74  erhic::Pid Id() const {
75  //printf("%d\n", mRcPdgCode); fflush(stdout);
76  return ::erhic::Pid(mRcPdgCode);
77  }
78 
79  // Particle mass; remember, fRcPdg PDG code is ALWAYS available, no matter what;
80  virtual Double_t GetM() const { return Id().Info()->Mass(); };
81 
82  // Yes, as trivial as that; THINK: this may all break once I start working with
83  // resonances; well, even there may decouple invariant mass value from the "true"
84  // mass of identified particle;
85  virtual Double_t GetE() const { return sqrt(pow(GetP(), 2) + pow(GetM(), 2)); };
86 
87  // (E,p) 4-vector in the lab frame; FIXME: not the most efficient call -
88  // see GetE()->GetM(); may want to optimize later;
89  virtual TLorentzVector Get4Vector() const {
90  return TLorentzVector(GetPx(), GetPy(), GetPz(), GetE());
91  };
92 
93  // FIXME: this call needs to be implemented properly;
94  virtual UShort_t GetStatus() const { exit(0); };
95  // Dummy one; just need to compile;
96  void Set4Vector(const TLorentzVector&) {};
97  // Same as in ParticleMCS, whatever it is good for ...;
98  virtual UShort_t GetParentIndex() const { return 0; }
99 
100  // ------------- various interface calls
101 
102  // Get indices in erhic::VirtualParticle, PidChargedCand and PndMCTrack arrays;
103  int GetGeneratorIndex() const { return mGeneratorEventIndex; }
105  int GetPndMCTrackIndex() const { return mPndMCTrackIndex; }
106 
107  // Well, may want to access other variables in the related PndMCTrack
108  // and PndPidCandidate arrays; EicRcParticle class itself has only a limited
109  // set of variables copied over (possibly symmetric in MC and RC);
110  const PndMCTrack* GetPndMcTrack() const;
111  // .. and respective shortcut;
112  const PndMCTrack* pndmc() const { return GetPndMcTrack(); };
113  // In particular PndPidCandidate has a plenty of various crap in;
114  const PndPidCandidate* GetPndPidCandidate() const;
115  // .. and respective shortcut;
116  const PndPidCandidate* pndrc() const { return GetPndPidCandidate(); };
117  // In this case just return the stored pointer;
118  const erhic::ParticleMC* GetGeneratorTrack() const;
119  // .. and respective shortcut;
120  const erhic::ParticleMC* genmc() const { return GetGeneratorTrack(); };
121 
122  // For completeness ...;
123  const EicRcParticle* eicrc() const { return this; };
124 
125  //
126  // Well, I sort of want to remain sitting on two chairs:
127  // 1) want to have symmetric access to similar variables in EventMC and EicRcEvent
128  // (so fill out pointer vectors there in the same order (with 0 pointer "gaps"
129  // in reconstructed vector, to be specific); this is governed in part by
130  // erhic::VirtualParticle-related methods above;
131  // 2) also want to retain symmetric access to basic simulated and reconstructed
132  // variables (like momentum and vertex coordinates) even if erhic::VirtualParticle
133  // entries are missing (eg Box generator used for detector studies); so maintain
134  // a second set of methods right here which allow convenient access;
135  //
136 
137  // Get MC and reconstructed 3D vertex; if performance in access to MC variables this
138  // way ever becomes a problem, use local variables and fill them out once right at a
139  // time of EicRcParticle creation; FIXME: in this case may want to use TVector3&, etc
140  // as return values;
141  const TVector3 GetMcVertex() const {
142  // FIXME: May want to cache at least this pointer;
143  const PndMCTrack *mctrack = GetPndMcTrack();
144 
145  return mctrack ? mctrack->GetStartVertex() : TVector3();
146  };
147  const TVector3 GetRcVertex() const { return mRcVertex; }
148 
149 
150  // Get MC and reconstructed 3D momentum at vertex;
151  const TVector3 GetMcVtxMomentum() const {
152  const PndMCTrack *mctrack = GetPndMcTrack();
153 
154  return mctrack ? mctrack->GetMomentum() : TVector3();
155  };
156  const TVector3 GetRcVtxMomentum() const { return mRcVtxMomentum; }
158  // A hack for test purposes;
160 
161  // Get MC and PID-reconstructed particle type;
162  int GetMcPdgCode() const {
163  const PndMCTrack *mctrack = GetPndMcTrack();
164 
165  // Yes, return 0 if unknown (hmm, say reconstructed ghost track, or Rec->MC
166  // match failed or PndMCTrack entries are not available, etc);
167  return mctrack ? mctrack->GetPdgCode() : 0;
168  };
169  int GetRcPdgCode() const { return mRcPdgCode; }
170 
171  double GetEmCalEnergy() const { return mEmCal ? mEmCal->mEnergy : 0.0; };
172  double GetHCalEnergy() const { return mHCal ? mHCal->mEnergy : 0.0; };
173 
174  private:
175  // NB: leave them signed (-1 is a "non-assigned" indicator);
176  int mGeneratorEventIndex; // index in erhic::VirtualEvent array (in case of generator input)
177  int mPndMCTrackIndex; // index in PandaRoot PndMCTrack array
178  int mPndPidChargedCandIndex; // index in PandaRoot PidChargedCand array
179 
180  // FIXME: link to the EicRcVertex class should be implemented later;
181  //EicRcVertex *RcVertex() { return 0; }
182  //int fVertexId; // index in EicRcVertex clone array
183 
184  public:
185  // I guess to the moment do not need more options?; extend later if needed;
187 
188  private:
189  //
190  // PID procedure - PDG definition logic - (to be) implemented:
191  //
192  // - PDG code is ALWAYS assigned to some valid non-zero number; the meaning and confidence
193  // level are moderated by accompanying variables;
194  //
195  // - assume, that if track is available, charge can ALWAYS be determined (at least
196  // with a 50% probability if a straight track in no field :-);
197  //
198  // - tracking (TR) used for momentum and charge sign determination;
199  // - {TR,ECAL} and/or {ECAL,HCAL} used for electron/hadron separation (EPID);
200  // - RICH used for pion/kaon/proton separation (HPID); THINK: well, in fact can be used
201  // for electron ID as well?;
202  //
203  // OPTIONS:
204  // ========
205  //
206  // A) charged track is registered -> fChargeDefCL in the range [0.5 .. 1.0]:
207  // -------------------------------------------------------------------------
208  // - A1: EPID & HPID Ok -> PID-based value: +/-(11/211/321/2212);
209  // fElectronPidCL assigned; fHadronPidCL assigned;
210  // - A2: no HPID info -> if electron : +/-11; fElectronPidCL assigned; fHadronPidCL empty;
211  // -> if hadron : +/-211 (pion); fElectronPidCL assigned; fHadronPidCL empty;
212  // - A3: no EPID info -> if pion : +/-211; fElectronPidCL=0; fHadronPidCL assigned;
213  // -> if kaon/proton : +/-(321/2212); fElectronPidCL assigned based on either PionKaon
214  // or PionProton; fHadronPidCL assigned;
215  // - A3: no EPID & HPID -> : +/-211 (pion); fElectronPidCL=0; fHadronPidCL empty;
216  //
217  // B) no charged track in tracker acceptance -> fChargeDefCL = 1.0 (or whatever tracking inefficiency):
218  // ----------------------------------------------------------------------------------------------------
219  // - B1: EPID available -> : EPID-based, either 22 (gamma) or 111 (pi^0); yes, assume pi^0;
220  // fElectronPidCL assigned; fHadronPidCL empty;
221  // - B1: no EPID -> : 111 (pi^0); yes, assume pi^0;
222  // fElectronPidCL=0; fHadronPidCL empty;
223  //
224  // C) track would be out of tracker acceptance (say, high |eta|) -> fChargeDefCL = 0.0:
225  // ------------------------------------------------------------------------------------
226  // - C1: EPID available -> : EPID-based, either 22 (gamma) or 111 (pi^0);
227  // fElectronPidCL assigned; fHadronPidCL empty;
228  // - C1: no EPID -> : 111 (pi^0); yes, assume pi^0;
229  // fElectronPidCL=0; fHadronPidCL empty;
230  //
231 
232  int mRcPdgCode; // PID-based (or wildly guessed) PDG code (see above)
233  // Well, something like expected fraction of 1/p gaussian tail extending to opposite charge;
234  float mChargeDefCL; // charge definition confidence level in the range [0.5 .. 1.0]
235  float mElectronPidCL; // electron/hadron separation confidence level in PDG assignment
236  // Looks too much tricky, but leave as it is for now; typically will be just
237  // one pair here I guess; leave some freedom for more complicated cases though;
238  // access through GetHadronPidCL() shoud hide the details;
239  std::vector< std::pair<HadronPidType, float> > mHadronPidCL; // available hadron separation CLs
240 
241  //
242  // These variables I want to have separately instead of extracting them on-the-fly
243  // because the assignment differs between charged particles, gammas, decay particles, etc;
244  //
245 
246  // Taken either from tracking (if track is available) or remains (0,0,0) if only calorimeter
247  // cluster information is available;
248  TVector3 mRcVertex; // reconstructed track 3D vertex
249 
250  //
251  // Well, consider a bit naive logic here:
252  //
253  // - assume, that this variable contains both 1D energy and 3D momentum
254  // information properly weighted to pack best knowledge particle kinematics;
255  // - assume PID info is ALWAYS available (see fRcPdg above and comments there),
256  // so use that PDG mass in the calculation;
257  // - GetE() in this approach just trivially returns sqrt(p^2+m^2), NOT
258  // the calorimeter energy;
259  //
260  // FIXME: later there should be easy way to access original 3D (tracker) momentum
261  // and original calorimeter energy variables;
262  //
263  // NB: since Kinematics.cxx routines use momentum if it is available,
264  // this approach should work there (or be a good start, at least);
265  //
266  // NB: Kalman filter is assumed to be re-run with anticipated PID hypothesis
267  // (well, FIXME: so far pion hypothesis is always used), so everything should
268  // be sort of consistent, right?;
269  TVector3 mRcVtxMomentum; // reconstructed track 3D momentum at the vertex
270  Double_t mRcTrackerMomentumSigma; // diagonal error on momentum magnitude
271 
272 #if _OLD_
273  // Well, the idea is that no matter how track-to-cluster and cluster-to-cluster
274  // (in different calorimeters) association is made, at the end EicRcParticle class
275  // instance contains links to calorimeter cluster groups in some of the calorimeters,
276  // which was sufficient to calculate energy deposit fraction and 3D location of hit
277  // related to this particle; the higher level code may the proceed to 1) combine EmCal
278  // information into the final estimate of e/m energy (indeed eg FEMC and CEMC may
279  // have energy deposits from the same track), 2) calculate weighted mean momentum&energy
280  // 3D kinematics at the IP, 3) perform necessary PID assignments based on e/p and hadronic
281  // calorimeter signal; FIXME: perhaps vectors and enum stuff would be better?;
282 #endif
283  std::vector<std::pair<unsigned, unsigned> > mCellGroups; // cell group IDs of clusters which were used to estimate energy & location
285 
286  ClassDef(EicRcParticle, 16);
287 };
288 
289 #endif