Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RICHParticleID.C
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file RICHParticleID.C
1 #include "RICHParticleID.h"
2 #include "PidInfo_RICH_v1.h"
3 #include "PidInfoContainer.h"
4 #include "TrackProjectorPid.h"
6 #include "PIDProbabilities.h"
7 
8 // Fun4All includes
11 
12 #include <phool/getClass.h>
13 #include <phool/PHCompositeNode.h>
14 
15 #include <g4main/PHG4Hit.h>
17 #include <g4main/PHG4Particle.h>
18 #include <g4main/PHG4VtxPoint.h>
20 
21 #include <g4hough/SvtxTrackMap.h>
22 #include <g4hough/SvtxTrack.h>
23 #include <g4hough/SvtxTrackState.h>
24 
25 // ROOT includes
26 #include <TTree.h>
27 #include <TFile.h>
28 #include <TString.h>
29 #include <TMath.h>
30 #include <TH1.h>
31 
32 // other C++ includes
33 #include <cassert>
34 #include <algorithm>
35 
36 using namespace std;
37 
39  SubsysReco("RICHParticleID" ),
40  _ievent(0),
41  _detector(richname),
42  _trackmap_name(tracksname),
43  _refractive_index(1),
44  _pidinfos(nullptr),
45  _trackproj(nullptr),
46  _acquire(nullptr),
47  _particleid(nullptr),
48  _radius(220.)
49 {
50  _richhits_name = "G4HIT_" + _detector;
51  _pidinfo_node_name = "PIDINFO_" + _detector;
52 }
53 
54 
55 int
57 {
58  _verbose = false;
59  _ievent = 0;
60 
61  /* create particleid object */
63 
64  /* Throw warning if refractive index is not greater than 1 */
65  if ( _refractive_index <= 1 )
66  cout << PHWHERE << " WARNING: Refractive index for radiator volume is " << _refractive_index << endl;
67 
68  return 0;
69 }
70 
71 
72 int
74 {
75  /* Create nodes for ParticleID */
76  try
77  {
78  CreateNodes(topNode);
79  }
80  catch (std::exception &e)
81  {
82  std::cout << PHWHERE << ": " << e.what() << std::endl;
83  throw;
84  }
85 
86  /* create track projector object */
87  _trackproj = new TrackProjectorPid( topNode );
88 
89  /* create acquire object */
91 
92  return 0;
93 }
94 
95 
96 int
98 {
99  _ievent ++;
100 
101  /* Get truth information (temporary) */
102  PHG4TruthInfoContainer* truthinfo = findNode::getClass<PHG4TruthInfoContainer>(topNode, "G4TruthInfo");
103 
104  /* Get all photon hits in RICH for this event */
105  PHG4HitContainer* richhits = findNode::getClass<PHG4HitContainer>(topNode,_richhits_name);
106 
107  /* Get track collection with all tracks in this event */
108  SvtxTrackMap* trackmap = findNode::getClass<SvtxTrackMap>(topNode,_trackmap_name);
109 
110  /* Check if collections found */
111  if (!truthinfo) {
112  cout << PHWHERE << "PHG4TruthInfoContainer not found on node tree" << endl;
114  }
115  if (!richhits) {
116  cout << PHWHERE << "PHG4HitContainer not found on node tree" << endl;
118  }
119  if (!trackmap) {
120  cout << PHWHERE << "SvtxTrackMap node not found on node tree" << endl;
122  }
123 
124 
125  /* Loop over tracks */
126  for (SvtxTrackMap::ConstIter track_itr = trackmap->begin(); track_itr != trackmap->end(); track_itr++)
127  {
128 
129  bool use_reconstructed_momentum = true;
130  bool use_truth_momentum = false;
131  bool use_emission_momentum = false;
132 
133  bool use_reconstructed_point = true;
134  bool use_approximate_point = false;
135 
136 
137  SvtxTrack* track_j = dynamic_cast<SvtxTrack*>(track_itr->second);
138 
139  /* Check if track_j is a null pointer. */
140  if (track_j == NULL)
141  continue;
142 
143  /* See if there's already a PidInfo object for this track. If yes, retrieve it- if not, create a new one. */
144  PidInfo *pidinfo_j = _pidinfos->getPidInfo( track_j->get_id() );
145  if (!pidinfo_j)
146  {
147  pidinfo_j = new PidInfo_RICH_v1( track_j->get_id() );
148  _pidinfos->AddPidInfo( pidinfo_j );
149  }
150 
151  /* Fill momv object which is the normalized momentum vector of the track in the RICH (i.e. its direction) */
152  double momv[3] = {0.,0.,0.};
153 
154  if (use_reconstructed_momentum) {
155  /* 'Continue' with next track if RICH projection not found for this track */
157  {
158  cout << "RICH track projection momentum NOT FOUND; next iteration" << endl;
159  continue;
160  }
161  }
162  if (use_truth_momentum) {
163  /* Fill with truth momentum instead of reco */
164  if ( ! _acquire->get_true_momentum( truthinfo, track_j, momv) )
165  {
166  cout << "No truth momentum found for track; next iteration" << endl;
167  continue;
168  }
169  }
170  if (use_emission_momentum) {
171  /* Fill with vector constructed from emission points (from truth) */
172  if ( ! _acquire->get_emission_momentum( truthinfo, richhits, track_j, momv) )
173  {
174  cout << "No truth momentum from emission points found for track; next iteration" << endl;
175  continue;
176  }
177  }
178 
179  double momv_norm = sqrt( momv[0]*momv[0] + momv[1]*momv[1] + momv[2]*momv[2] );
180  momv[0] /= momv_norm;
181  momv[1] /= momv_norm;
182  momv[2] /= momv_norm;
183 
184 
185  /* Get mean emission point from track in RICH */
186  double m_emi[3] = {0.,0.,0.};
187 
188  if (use_reconstructed_point) {
189  /* 'Continue' with next track if RICH projection not found for this track */
191  {
192  cout << "RICH track projection position NOT FOUND; next iteration" << endl;
193  continue;
194  }
195  }
196  if (use_approximate_point) {
197  m_emi[0] = ((_radius)/momv[2])*momv[0];
198  m_emi[1] = ((_radius)/momv[2])*momv[1];
199  m_emi[2] = ((_radius)/momv[2])*momv[2];
200  }
201 
202 
203  /* 'Continue' with next track if track doesn't pass through RICH */
204  if ( ! _trackproj->is_in_RICH( momv ) )
205  continue;
206 
207 
208  //cout << "Emission point: " << m_emi[0] << " " << m_emi[1] << " " << m_emi[2] << endl;
209  //cout << "Momentum vector: " << momv[0] << " " << momv[1] << " " << momv[2] << endl;
210 
211  /* Vector of reconstructed angles to pass to PID */
212  vector<float> angles;
213 
214 
215  /* Loop over all G4Hits in container (RICH photons in event) */
216  PHG4HitContainer::ConstRange rich_hits_begin_end = richhits->getHits();
217  PHG4HitContainer::ConstIterator rich_hits_iter;
218 
219  for (rich_hits_iter = rich_hits_begin_end.first; rich_hits_iter != rich_hits_begin_end.second; ++rich_hits_iter)
220  {
221 
222  PHG4Hit *hit_i = rich_hits_iter->second;
223 
224  /* Calculate reconstructed emission angle for output, fill Cherenkov array */
225  double _theta_reco = _acquire->calculate_emission_angle( m_emi, momv, hit_i );
226  angles.push_back(_theta_reco);
227 
228  } // END loop over photons
229 
230 
231  /* Calculate particle probabilities */
232  long double probs[4] = {0.,0.,0.,0.};
233  double momv_magnitude = 0;
234 
235  /* Emission point momentum only gives a valid unit vector, not magnitude */
236  if ( use_reconstructed_momentum )
237  momv_magnitude = momv_norm;
238  if ( use_truth_momentum )
239  momv_magnitude = momv_norm;
240  if ( use_emission_momentum )
241  {
242  PHG4Particle* particle = truthinfo->GetParticle( track_j->get_truth_track_id() );
243  double px = particle->get_px();
244  double py = particle->get_py();
245  double pz = particle->get_pz();
246  momv_magnitude = sqrt( px*px + py*py + pz*pz );
247  }
248 
249  if ( !_particleid->particle_probs( angles, momv_magnitude, _refractive_index, probs ) )
250  {
251  cout << "No particle ID: ParticleID::particle_probs gives no output" << endl;
252  continue;
253  }
254 
255  /* Set particle probabilities */
256  pidinfo_j->set_likelihood(PidInfo::ELECTRON, probs[0]);
257  pidinfo_j->set_likelihood(PidInfo::CHARGEDPION, probs[1]);
258  pidinfo_j->set_likelihood(PidInfo::CHARGEDKAON, probs[2]);
259  pidinfo_j->set_likelihood(PidInfo::PROTON, probs[3]);
260 
261  } // END loop over tracks
262 
263  return 0;
264 }
265 
266 int
268 {
269  return 0;
270 }
271 
273 {
274  PHNodeIterator iter(topNode);
275 
276  PHCompositeNode *dstNode = static_cast<PHCompositeNode*>(iter.findFirst("PHCompositeNode", "DST"));
277  if (!dstNode)
278  {
279  std::cerr << PHWHERE << "DST Node missing, doing nothing." << std::endl;
280  throw std::runtime_error("Failed to find DST node in RICHParticleID::CreateNodes");
281  }
282 
283  PHNodeIterator dstiter(dstNode);
284  PHCompositeNode *DetNode = dynamic_cast<PHCompositeNode*>(dstiter.findFirst("PHCompositeNode",_detector ));
285  if(!DetNode){
286  DetNode = new PHCompositeNode(_detector);
287  dstNode->addNode(DetNode);
288  }
289 
290  _pidinfos = new PidInfoContainer();
291  PHIODataNode<PHObject> *pidInfoNode = new PHIODataNode<PHObject>(_pidinfos, _pidinfo_node_name.c_str(), "PHObject");
292  DetNode->addNode(pidInfoNode);
293 }