EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
functions.cxx
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file functions.cxx
1 
10 #include "eicsmear/functions.h"
11 
12 #include <cmath>
13 #include <fstream>
14 #include <set>
15 #include <sstream>
16 #include <string>
17 
18 #include <TLorentzVector.h>
19 #include <TMath.h>
20 #include <TParticlePDG.h>
21 #include <TVector2.h>
22 #include <TVector3.h>
23 
24 #include "eicsmear/erhic/EventMC.h"
26 
31 char getFirstNonBlank(const std::string& line) {
32  char first('\0'); // NULL character by default
33  // Find the index first non-blank character.
34  size_t index = line.find_first_not_of(" \t");
35 
36  if (index != std::string::npos) {
37  first = line.at(index);
38  } // if
39 
40  return first;
41 }
42 
51 double
52 computeHermesPhiH(const TLorentzVector& hadronInPrf,
53  const TLorentzVector& leptonInPrf,
54  const TLorentzVector& photonInPrf) {
55  const TVector3& q = photonInPrf.Vect();
56  const TVector3& k = leptonInPrf.Vect();
57  const TVector3& Ph = hadronInPrf.Vect();
58  const TVector3& qCrossK = q.Cross(k);
59  const TVector3& qCrossPh = q.Cross(Ph);
60  // Used to determine spin direction:
61  double qCrossKDotPh = qCrossK.Dot(Ph);
62  if (::fabs(qCrossKDotPh) < 1.0e-5) return -999.0;
63 
64  // First get phi in the range [0,pi]:
65  double phi = TMath::ACos(qCrossK.Dot(qCrossPh)
66  / qCrossK.Mag()
67  / qCrossPh.Mag());
68 
69  // Handle spin direction to get result in range [-pi,pi] by
70  // scaling by [-1,+1], depending on hemisphere.
71  phi *= qCrossKDotPh / ::fabs(qCrossKDotPh);
72 
73  return TVector2::Phi_0_2pi(phi);
74 }
75 
76 //
77 // class EventToDot.
78 //
79 
80 struct Pair {
81  int a;
82  int b;
83  Pair(int x, int y) : a(x), b(y) { }
84  // Less-than operator required for entry in sorted container.
85  bool operator<(const Pair& other) const {
86  if (other.a == a) return b < other.b;
87  return a < other.a;
88  }
89 };
90 
91 
93  const std::string& name) const {
94  std::ofstream file(name.c_str());
95  std::ostringstream oss;
96 
97  file << "digraph G {" << std::endl;
98  oss << " label = \"Event " << event.GetN() << "\"';";
99  file << oss.str() << std::endl;
100 
101  std::set<Pair> pairs;
102 
103  // Keep track of which particles we use in the diagram
104  // so we can set node attributes at the end.
105  // Use a set to avoid worrying about adding duplicates.
106  std::set<const erhic::ParticleMC*> used;
107 
108  // Loop over all tracks in the event and accumulate indices giving
109  // parent/child relationships.
110  // We look from parent->child and child->parent because they
111  // aren't always fully indexed both ways.
112  for (unsigned i(0); i < event.GetNTracks(); ++i) {
113  // Check parent of particle
114  const erhic::ParticleMC* parent = event.GetTrack(i)->GetParent();
115  if (parent) {
116  pairs.insert(Pair(parent->GetIndex(), event.GetTrack(i)->GetIndex()));
117  used.insert(parent);
118  used.insert(event.GetTrack(i));
119  } // if
120  // Check children of particle
121  for (unsigned j(0); j < event.GetTrack(i)->GetNChildren(); ++j) {
122  pairs.insert(Pair(event.GetTrack(i)->GetIndex(),
123  event.GetTrack(i)->GetChild(j)->GetIndex()));
124  used.insert(event.GetTrack(i));
125  used.insert(event.GetTrack(i)->GetChild(j));
126  } // for
127  } // for
128  // Insert relationships between particles.
129  for (std::set<Pair>::const_iterator i = pairs.begin();
130  i != pairs.end();
131  ++i) {
132  const erhic::ParticleMC* a = event.GetTrack(i->a - 1);
133  const erhic::ParticleMC* b = event.GetTrack(i->b - 1);
134  oss.str("");
135  oss << " " << a->GetIndex() << " -> " <<
136  b->GetIndex();
137  file << oss.str() << std::endl;
138  } // for
139  file << "# Node attributes" << std::endl;
140  // Apply labels, formatting to used particles.
141  for (std::set<const erhic::ParticleMC*>::const_iterator i = used.begin();
142  i != used.end();
143  ++i) {
144  std::string shape("ellipse");
145  if ((*i)->GetStatus() == 1) {
146  shape = "box";
147  } // if
148  if ((*i)->GetIndex() < 3) {
149  shape = "diamond";
150  } // if
151  oss.str("");
152  oss << " " << (*i)->GetIndex() << " [label=\"" << (*i)->GetIndex() << " ";
153  if ((*i)->Id().Info()) {
154  oss << (*i)->Id().Info()->GetName();
155  } else {
156  oss << "unknown PDG " << (*i)->Id().Code();
157  } // if
158  oss << "\", shape=" << shape << "];";
159  file << oss.str() << std::endl;
160  } // for
161  file << "}";
162 }