EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PHG4Utils.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file PHG4Utils.cc
1 #include "PHG4Utils.h"
2 
3 #include <phool/phool.h>
4 
5 #include <Geant4/G4Colour.hh> // for G4Colour
6 #include <Geant4/G4VisAttributes.hh>
7 
8 #include <TSystem.h>
9 
10 #include <boost/algorithm/hex.hpp>
11 #include <boost/algorithm/string.hpp>
12 #include <boost/uuid/detail/md5.hpp>
13 
14 #include <algorithm> // for copy
15 #include <cmath>
16 #include <cstdlib> // for exit
17 #include <fstream>
18 #include <iostream> // for operator<<, endl, basic_ostream
19 #include <iterator> // for back_insert_iterator
20 #include <vector> // for vector
21 
22 using namespace std;
23 
24 double PHG4Utils::_eta_coverage = 1.;
25 
26 double
28 {
29  double length;
30  double theta = 2.0 * std::atan(std::exp(-eta));
31  length = radius / std::tan(theta);
32  return length;
33 }
34 
35 double
37 {
38  return GetLengthForRapidityCoverage(radius, _eta_coverage);
39 }
40 
42 {
43  _eta_coverage = eta;
44 }
45 
46 double
48 {
49  double theta = 2 * atan(exp(-eta));
50  return theta;
51 }
52 
53 double
55 {
56  double eta = -log(tan(theta / 2.));
57  return eta;
58 }
59 
60 pair<double, double>
61 PHG4Utils::get_etaphi(const double x, const double y, const double z)
62 {
63  double eta;
64  double phi;
65  double radius;
66  double theta;
67  radius = sqrt(x * x + y * y);
68  phi = atan2(y, x);
69  theta = atan2(radius, z);
70  eta = -log(tan(theta / 2.));
71  return make_pair(eta, phi);
72 }
73 
74 double
75 PHG4Utils::get_eta(const double radius, const double z)
76 {
77  double eta;
78  double theta;
79  theta = atan2(radius, fabs(z));
80  eta = -log(tan(theta / 2.));
81  if (z < 0)
82  {
83  eta = -eta;
84  }
85  return eta;
86 }
87 
88 void PHG4Utils::SetColour(G4VisAttributes* att, const string& material)
89 {
90  if (!att)
91  {
92  cout << "G4VisAttributes pointer is NULL" << endl;
93  return;
94  }
95  if (material == "AL_BABAR_MAG")
96  {
97  att->SetColour(G4Colour::Blue());
98  }
99  else if (material == "BlackHole")
100  {
101  att->SetColour(G4Colour::Black());
102  }
103  else if (material == "C4F10")
104  {
105  att->SetColour(0., 0., 0.5, 0.25);
106  }
107  else if (material == "CF4")
108  {
109  att->SetColour(G4Colour::Magenta());
110  }
111  else if (material == "G4_AIR")
112  {
113  att->SetColour(G4Colour::Black());
114  }
115  else if (material == "G4_Al")
116  {
117  att->SetColour(G4Colour::Gray());
118  }
119  else if (material == "G4_Au")
120  {
121  att->SetColour(G4Colour::Yellow());
122  }
123  else if (material == "G4_CARBON_DIOXIDE")
124  {
125  att->SetColour(G4Colour::Green());
126  }
127  else if (material == "G4_CELLULOSE_CELLOPHANE")
128  {
129  att->SetColour(0.25, 0.25, 0.);
130  }
131  else if (material == "G4_Cu")
132  {
133  att->SetColour(1., 0.51, 0.278);
134  }
135  else if (material == "G4_Fe")
136  {
137  att->SetColour(0.29, 0.44, 0.54);
138  }
139  else if (material == "G4_KAPTON")
140  {
141  att->SetColour(G4Colour::Yellow());
142  }
143  else if (material == "G4_MYLAR")
144  {
145  att->SetColour(0.5, 0.5, 0.5, 0.25);
146  }
147  else if (material == "G4_METHANE")
148  {
149  att->SetColour(0., 1., 1., 0.25);
150  }
151  else if (material == "G4_Si")
152  {
153  att->SetColour(G4Colour::Yellow());
154  }
155  else if (material == "G4_TEFLON")
156  {
157  att->SetColour(G4Colour::White());
158  }
159  else if (material == "G4_W")
160  {
161  att->SetColour(0.36, 0.36, 0.36);
162  }
163  else if (material == "Quartz")
164  {
165  att->SetColour(G4Colour::Green());
166  }
167  else if (material == "Scintillator" || material == "G4_POLYSTYRENE")
168  {
169  att->SetColour(0., 1., 1.);
170  }
171  else if (material == "W_Epoxy")
172  {
173  att->SetColour(0.5, 0.5, 0.5);
174  }
175  else if (material == "G10")
176  {
177  att->SetColour(1., 1., 0., 0.5);
178  }
179  else
180  {
181  //cout << "default color red for material " << material << endl;
182  att->SetColour(G4Colour::Cyan());
183  }
184  return;
185 }
186 // returns success/failure and intersection point (x/y)
187 std::pair<bool, std::pair<double, double>> PHG4Utils::lines_intersect(
188  double ax,
189  double ay,
190  double bx,
191  double by,
192  double cx,
193  double cy,
194  double dx,
195  double dy)
196 {
197  // Find if a line segment limited by points A and B
198  // intersects line segment limited by points C and D.
199  // First check if an infinite line defined by A and B intersects
200  // segment (C,D). If h is from 0 to 1 line and line segment intersect
201  // Then check in intersection point is between C and D
202  double ex = bx - ax; // E=B-A
203  double ey = by - ay;
204  double fx = dx - cx; // F=D-C
205  double fy = dy - cy;
206  double px = -ey; // P
207  double py = ex;
208 
209  double bottom = fx * px + fy * py; // F*P
210  double gx = ax - cx; // A-C
211  double gy = ay - cy;
212  double top = gx * px + gy * py; // G*P
213 
214  double h = 99999.;
215  if (bottom != 0.)
216  {
217  h = top / bottom;
218  }
219 
220  //intersection point R = C + F*h
221  if (h > 0. && h < 1.)
222  {
223  double rx = cx + fx * h;
224  double ry = cy + fy * h;
225  //cout << " line/segment intersection coordinates: " << *rx << " " << *ry << endl;
226  if ((rx > ax && rx > bx) || (rx < ax && rx < bx) || (ry < ay && ry < by) || (ry > ay && ry > by))
227  {
228  //cout << " NO segment/segment intersection!" << endl;
229  return make_pair(false, make_pair(NAN, NAN));
230  }
231  else
232  {
233  //cout << " segment/segment intersection!" << endl;
234  return make_pair(true, make_pair(rx, ry));
235  }
236  }
237 
238  return make_pair(false, make_pair(NAN, NAN));
239 }
240 
241 // returns success/failure and length of the line segment inside the rectangle (output)
243  double ax,
244  double ay,
245  double bx,
246  double by,
247  double cx,
248  double cy,
249  double dx,
250  double dy)
251 {
252  // find if a line isegment limited by points (A,B)
253  // intersects with a rectangle defined by two
254  // corner points (C,D) two other points are E and F
255  // E--------D
256  // | |
257  // | |
258  // C--------F
259 
260  if (cx > dx || cy > dy)
261  {
262  cout << PHWHERE << "ERROR: Bad rectangle definition!" << endl;
263  return make_pair(false, NAN);
264  }
265 
266  double ex = cx;
267  double ey = dy;
268  double fx = dx;
269  double fy = cy;
270 
271  vector<double> vx;
272  vector<double> vy;
273  pair<bool, pair<double, double>> intersect1 = lines_intersect(ax, ay, bx, by, cx, cy, fx, fy);
274  // bool i1 = lines_intersect(ax, ay, bx, by, cx, cy, fx, fy, &rx, &ry);
275  if (intersect1.first)
276  {
277  vx.push_back(intersect1.second.first);
278  vy.push_back(intersect1.second.second);
279  }
280  pair<bool, pair<double, double>> intersect2 = lines_intersect(ax, ay, bx, by, fx, fy, dx, dy);
281  // bool i2 = lines_intersect(ax, ay, bx, by, fx, fy, dx, dy, &rx, &ry);
282  if (intersect2.first)
283  {
284  vx.push_back(intersect2.second.first);
285  vy.push_back(intersect2.second.second);
286  }
287  pair<bool, pair<double, double>> intersect3 = lines_intersect(ax, ay, bx, by, ex, ey, dx, dy);
288  // bool i3 = lines_intersect(ax, ay, bx, by, ex, ey, dx, dy, &rx, &ry);
289  if (intersect3.first)
290  {
291  vx.push_back(intersect3.second.first);
292  vy.push_back(intersect3.second.second);
293  }
294  pair<bool, pair<double, double>> intersect4 = lines_intersect(ax, ay, bx, by, cx, cy, ex, ey);
295  // bool i4 = lines_intersect(ax, ay, bx, by, cx, cy, ex, ey, &rx, &ry);
296  if (intersect4.first)
297  {
298  vx.push_back(intersect4.second.first);
299  vy.push_back(intersect4.second.second);
300  }
301 
302  //cout << "Rectangle intersections: " << i1 << " " << i2 << " " << i3 << " " << i4 << endl;
303  //cout << "Number of intersections = " << vx.size() << endl;
304 
305  double rr = 0.;
306  if (vx.size() == 2)
307  {
308  rr = sqrt((vx[0] - vx[1]) * (vx[0] - vx[1]) + (vy[0] - vy[1]) * (vy[0] - vy[1]));
309  // cout << "Length of intersection = " << *rr << endl;
310  }
311  if (vx.size() == 1)
312  {
313  // find which point (A or B) is within the rectangle
314  if (ax > cx && ay > cy && ax < dx && ay < dy) // point A is inside the rectangle
315  {
316  //cout << "Point A is inside the rectangle." << endl;
317  rr = sqrt((vx[0] - ax) * (vx[0] - ax) + (vy[0] - ay) * (vy[0] - ay));
318  }
319  if (bx > cx && by > cy && bx < dx && by < dy) // point B is inside the rectangle
320  {
321  //cout << "Point B is inside the rectangle." << endl;
322  rr = sqrt((vx[0] - bx) * (vx[0] - bx) + (vy[0] - by) * (vy[0] - by));
323  }
324  }
325 
326  if (intersect1.first || intersect2.first || intersect3.first || intersect4.first)
327  {
328  return make_pair(true, rr);
329  }
330  return make_pair(false, NAN);
331 }
332 
333 double PHG4Utils::sA(double r, double x, double y)
334 {
335  // Uses analytic formula for the integral of a circle between limits set by the corner of a rectangle
336  // It is called repeatedly to find the overlap area between the circle and rectangle
337  // I found this code implementing the integral on a web forum called "ars technica",
338  // https://arstechnica.com/civis/viewtopic.php?t=306492
339  // posted by "memp"
340 
341  double a;
342 
343  if (x < 0)
344  {
345  return -sA(r, -x, y);
346  }
347 
348  if (y < 0)
349  {
350  return -sA(r, x, -y);
351  }
352 
353  if (x > r)
354  {
355  x = r;
356  }
357 
358  if (y > r)
359  {
360  y = r;
361  }
362 
363  if (x * x + y * y > r * r)
364  {
365  a = r * r * asin(x / r) + x * sqrt(r * r - x * x) + r * r * asin(y / r) + y * sqrt(r * r - y * y) - r * r * M_PI_2;
366 
367  a *= 0.5;
368  }
369  else
370  {
371  a = x * y;
372  }
373 
374  return a;
375 }
376 
377 double PHG4Utils::circle_rectangle_intersection(double x1, double y1, double x2, double y2, double mx, double my, double r)
378 {
379  // Find the area of overlap of a circle and rectangle
380  // Calls sA, which uses an analytic formula to determine the integral of the circle between limits set by the corners of the rectangle
381 
382  // move the rectangle to the frame where the circle is at (0,0)
383  x1 -= mx;
384  x2 -= mx;
385  y1 -= my;
386  y2 -= my;
387 
388  // {
389  // cout << " mx " << mx << " my " << my << " r " << r << " x1 " << x1 << " x2 " << x2 << " y1 " << y1 << " y2 " << y2 << endl;
390  // cout << " sA21 " << sA(r, x2, y1)
391  // << " sA11 " << sA(r, x1, y1)
392  // << " sA22 " << sA(r, x2, y2)
393  // << " sA12 " << sA(r, x1, y2)
394  // << endl;
395  // }
396 
397  return sA(r, x2, y1) - sA(r, x1, y1) - sA(r, x2, y2) + sA(r, x1, y2);
398 }
399 
400 string PHG4Utils::md5sum(const std::string& filename)
401 {
402  ifstream myfile;
403  myfile.open(filename);
404  if (!myfile.is_open())
405  {
406  cout << "Error opening " << filename << endl;
407  gSystem->Exit(1);
408  exit(1);
409  }
410  boost::uuids::detail::md5 hash;
411  boost::uuids::detail::md5::digest_type digest;
412  char c;
413  while (myfile.get(c))
414  {
415  hash.process_bytes(&c, 1);
416  }
417  myfile.close();
418  hash.get_digest(digest);
419  const auto charDigest = reinterpret_cast<const char*>(&digest);
420  std::string result;
421  boost::algorithm::hex(charDigest, charDigest + sizeof(boost::uuids::detail::md5::digest_type), std::back_inserter(result));
422  boost::algorithm::to_lower(result);
423  return result;
424 }