Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PHHepMCGenHelper.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file PHHepMCGenHelper.cc
1 // $Id: $
2 
11 #include "PHHepMCGenHelper.h"
12 
13 #include "PHHepMCGenEvent.h"
14 #include "PHHepMCGenEventMap.h"
15 #include "PHHepMCGenEventv1.h"
16 
18 
19 #include <phool/PHCompositeNode.h>
20 #include <phool/PHIODataNode.h> // for PHIODataNode
21 #include <phool/PHNode.h> // for PHNode
22 #include <phool/PHNodeIterator.h> // for PHNodeIterator
23 #include <phool/PHObject.h> // for PHObject
24 #include <phool/PHRandomSeed.h>
25 #include <phool/getClass.h>
26 #include <phool/phool.h> // for PHWHERE
27 
28 #include <HepMC/SimpleVector.h> // for FourVector
29 
30 #include <CLHEP/Units/PhysicalConstants.h>
31 #include <CLHEP/Units/SystemOfUnits.h>
32 #include <CLHEP/Vector/Boost.h>
33 #include <CLHEP/Vector/LorentzRotation.h>
34 #include <CLHEP/Vector/LorentzVector.h>
35 #include <CLHEP/Vector/Rotation.h>
36 
37 #include <gsl/gsl_randist.h>
38 #include <gsl/gsl_rng.h>
39 
40 #include <cassert>
41 #include <cmath>
42 #include <cstdlib> // for exit
43 #include <iostream>
44 #include <limits>
45 
46 using namespace std;
47 
49  : _vertex_func_x(Gaus)
50  , _vertex_func_y(Gaus)
51  , _vertex_func_z(Gaus)
52  , _vertex_func_t(Gaus)
53  , _vertex_x(0)
54  , _vertex_y(0)
55  , _vertex_z(0)
56  , _vertex_t(0)
57  , _vertex_width_x(0)
58  , _vertex_width_y(0)
59  , _vertex_width_z(0)
60  , _vertex_width_t(0)
61  , _embedding_id(0)
62  , _reuse_vertex(false)
63  , _reuse_vertex_embedding_id(numeric_limits<int>::min())
64  , _geneventmap(nullptr)
65 {
66  RandomGenerator = gsl_rng_alloc(gsl_rng_mt19937);
67  unsigned int seed = PHRandomSeed(); // fixed seed is handled in this function
69 }
70 
72 {
73  gsl_rng_free(RandomGenerator);
74 }
75 
78 {
79  PHNodeIterator iter(topNode);
80  PHCompositeNode *dstNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "DST"));
81  if (!dstNode)
82  {
83  cout << PHWHERE << "DST Node missing doing nothing" << endl;
85  }
86 
87  _geneventmap = findNode::getClass<PHHepMCGenEventMap>(dstNode, "PHHepMCGenEventMap");
88  if (!_geneventmap)
89  {
91  PHIODataNode<PHObject> *newmapnode = new PHIODataNode<PHObject>(_geneventmap, "PHHepMCGenEventMap", "PHObject");
92  dstNode->addNode(newmapnode);
93  }
94 
96 
98 }
99 
102 {
103  // choice of version of PHHepMCGenEvent
104  const static PHHepMCGenEventv1 mc_evnet_template;
105 
106  return &mc_evnet_template;
107 }
108 
111 {
112  assert(evt);
114 
116 
117  genevent->addEvent(evt);
119 
120  return genevent;
121 }
122 
124 {
125  assert(genevent);
126 
127  assert(_vertex_width_x >= 0);
128  assert(_vertex_width_y >= 0);
129  assert(_vertex_width_z >= 0);
130  assert(_vertex_width_t >= 0);
131 
132  assert(not _reuse_vertex); // logic check
133 
134  // not reusing vertex so smear with the vertex parameters
135  genevent->moveVertex(
140 }
141 
145 double PHHepMCGenHelper::get_collision_width(unsigned int hv_index)
146 {
147  assert((hv_index == 0) or (hv_index == 1));
148 
149  const double widthA = m_beam_bunch_width.first[hv_index];
150  const double widthB = m_beam_bunch_width.second[hv_index];
151 
152  return widthA * widthB / sqrt(widthA * widthA + widthB * widthB);
153 }
154 
159 {
160  const pair<double, double> bunch_zs(
161  smear(
162  0, // central vertical angle shift
163  m_beam_bunch_width.first[2], // vertical angle smear
164  Gaus),
165  smear(
166  0, // central vertical angle shift
167  m_beam_bunch_width.second[2], // vertical angle smear
168  Gaus));
169 
170  CLHEP::Hep3Vector beamA_center = pair2Hep3Vector(m_beam_direction_theta_phi.first);
171  CLHEP::Hep3Vector beamB_center = pair2Hep3Vector(m_beam_direction_theta_phi.second);
172  // const static CLHEP::Hep3Vector z_axis(0, 0, 1);
173  const static CLHEP::Hep3Vector y_axis(0, 1, 0);
174 
175  // the final longitudinal vertex smear axis
176  CLHEP::Hep3Vector beamCenterDiffAxis = (beamA_center - beamB_center);
177  assert(beamCenterDiffAxis.mag() > CLHEP::Hep3Vector::getTolerance());
178  beamCenterDiffAxis = beamCenterDiffAxis / beamCenterDiffAxis.mag();
179 
180  CLHEP::Hep3Vector vec_crossing = beamA_center - 0.5 * (beamA_center - beamB_center);
181 
182  CLHEP::Hep3Vector vec_longitudinal_collision = beamCenterDiffAxis * (bunch_zs.first + bunch_zs.second) / 2.;
183  double ct_collision = 0.5 * (-bunch_zs.first + bunch_zs.second) / beamCenterDiffAxis.dot(beamA_center);
184  double t_collision = ct_collision * CLHEP::cm / CLHEP::c_light / CLHEP::ns;
185  CLHEP::Hep3Vector vec_crossing_collision = ct_collision * vec_crossing; // shift of collision to crossing dierction
186 
187  CLHEP::Hep3Vector horizontal_axis = y_axis.cross(beamCenterDiffAxis);
188  assert(horizontal_axis.mag() > CLHEP::Hep3Vector::getTolerance());
189  horizontal_axis = horizontal_axis / horizontal_axis.mag();
190 
191  CLHEP::Hep3Vector vertical_axis = beamCenterDiffAxis.cross(horizontal_axis);
192  assert(vertical_axis.mag() > CLHEP::Hep3Vector::getTolerance());
193  vertical_axis = vertical_axis / vertical_axis.mag();
194 
195  CLHEP::Hep3Vector vec_horizontal_collision_vertex_smear = horizontal_axis *
196  smear(
197  0,
199  Gaus);
200  CLHEP::Hep3Vector vec_vertical_collision_vertex_smear = vertical_axis *
201  smear(
202  0,
204  Gaus);
205 
206  CLHEP::Hep3Vector vec_collision_vertex =
207  vec_horizontal_collision_vertex_smear +
208  vec_vertical_collision_vertex_smear + //
209  vec_crossing_collision + vec_longitudinal_collision;
210 
211  genevent->set_collision_vertex(HepMC::FourVector(
212  vec_collision_vertex.x(),
213  vec_collision_vertex.y(),
214  vec_collision_vertex.z(),
215  t_collision));
216 
217  if (m_verbosity)
218  {
219  cout << __PRETTY_FUNCTION__
220  << ":"
221  << "bunch_zs.first = " << bunch_zs.first << ", "
222  << "bunch_zs.second = " << bunch_zs.second << ", "
223  << "cos(theta/2) = " << beamCenterDiffAxis.dot(beamA_center) << ", " << endl
224 
225  << "beamCenterDiffAxis = " << beamCenterDiffAxis << ", "
226  << "vec_crossing = " << vec_crossing << ", "
227  << "horizontal_axis = " << horizontal_axis << ", "
228  << "vertical_axis = " << vertical_axis << ", " << endl
229 
230  << "vec_longitudinal_collision = " << vec_longitudinal_collision << ", "
231  << "vec_crossing_collision = " << vec_crossing_collision << ", "
232  << "vec_vertical_collision_vertex_smear = " << vec_vertical_collision_vertex_smear << ", "
233  << "vec_horizontal_collision_vertex_smear = " << vec_horizontal_collision_vertex_smear << ", " << endl
234  << "vec_collision_vertex = " << vec_collision_vertex << ", " << endl
235 
236  << "ct_collision = " << ct_collision << ", "
237  << "t_collision = " << t_collision << ", "
238  << endl;
239  }
240 
241  return bunch_zs;
242 }
243 
244 CLHEP::Hep3Vector PHHepMCGenHelper::pair2Hep3Vector(const std::pair<double, double> &theta_phi)
245 {
246  const double &theta = theta_phi.first;
247  const double &phi = theta_phi.second;
248 
249  return CLHEP::Hep3Vector(
250  sin(theta) * cos(phi),
251  sin(theta) * sin(phi),
252  cos(theta));
253 }
254 
257 {
258  if (m_verbosity)
259  {
260  Print();
261  }
262 
263  assert(genevent);
264 
265  if (_reuse_vertex)
266  {
267  // just copy over the vertex boost_rotation_translation
268 
270 
271  PHHepMCGenEvent *vtx_evt =
273 
274  if (!vtx_evt)
275  {
276  cout << "PHHepMCGenHelper::HepMC2Lab_boost_rotation_translation - Fatal Error - the requested source subevent with embedding ID "
277  << _reuse_vertex_embedding_id << " does not exist. Current HepMCEventMap:";
279  exit(1);
280  }
281 
282  //copy boost_rotation_translation
283 
284  genevent->moveVertex(
285  vtx_evt->get_collision_vertex().x(),
286  vtx_evt->get_collision_vertex().y(),
287  vtx_evt->get_collision_vertex().z(),
288  vtx_evt->get_collision_vertex().t());
289 
290  genevent->set_boost_beta_vector(vtx_evt->get_boost_beta_vector());
291  genevent->set_rotation_vector(vtx_evt->get_rotation_vector());
292  genevent->set_rotation_angle(vtx_evt->get_rotation_angle());
293 
294  if (m_verbosity)
295  {
296  cout << __PRETTY_FUNCTION__ << ": copied boost rotation shift of the collision" << endl;
297  genevent->identify();
298  }
299  return;
300  }
301 
302  // now handle the collision vertex first, in the head-on collision frame
303  // this is used as input to the Crab angle correction
304  pair<double, double> beam_bunch_zs;
306  {
307  // bunch interaction simulation
308  beam_bunch_zs = generate_vertx_with_bunch_interaction(genevent);
309  }
310  else
311  {
312  // vertex distribution simulation
313  move_vertex(genevent);
314  const double init_vertex_longitudinal = genevent->get_collision_vertex().z();
315  beam_bunch_zs.first = beam_bunch_zs.second = init_vertex_longitudinal;
316  }
317 
318  // boost-rotation from beam angles
319 
320  const static CLHEP::Hep3Vector z_axis(0, 0, 1);
321 
322  CLHEP::Hep3Vector beamA_center = pair2Hep3Vector(m_beam_direction_theta_phi.first);
323  CLHEP::Hep3Vector beamB_center = pair2Hep3Vector(m_beam_direction_theta_phi.second);
324 
325  if (m_verbosity)
326  {
327  cout << __PRETTY_FUNCTION__ << ": " << endl;
328  cout << "beamA_center = " << beamA_center << endl;
329  cout << "beamB_center = " << beamB_center << endl;
330  }
331 
332  assert(fabs(beamB_center.mag2() - 1) < CLHEP::Hep3Vector::getTolerance());
333  assert(fabs(beamB_center.mag2() - 1) < CLHEP::Hep3Vector::getTolerance());
334 
335  if (beamA_center.dot(beamB_center) > -0.5)
336  {
337  cout << "PHHepMCGenHelper::HepMC2Lab_boost_rotation_translation - WARNING -"
338  << "Beam A and Beam B are not near back to back. "
339  << "Please double check beam direction setting at set_beam_direction_theta_phi()."
340  << "beamA_center = " << beamA_center << ","
341  << "beamB_center = " << beamB_center << ","
342  << " Current setting:";
343 
344  Print();
345  }
346 
347  // function to do angular shifts relative to central beam angle
348  auto smear_beam_divergence = [&, this](
349  const CLHEP::Hep3Vector &beam_center,
350  const std::pair<double, double> &divergence_hv,
351  const std::pair<double, double> &beam_angular_z_coefficient_hv) {
352  const double &x_divergence = divergence_hv.first;
353  const double &y_divergence = divergence_hv.second;
354 
355  // y direction in accelerator
356  static const CLHEP::Hep3Vector accelerator_plane(0, 1, 0);
357 
358  CLHEP::Hep3Vector beam_direction(beam_center);
359  CLHEP::HepRotation x_smear_in_accelerator_plane(
360  accelerator_plane,
361  smear(
362  beam_bunch_zs.first * beam_angular_z_coefficient_hv.first, // central horizontal angle shift
363  x_divergence, // horizontal angle smear
364  Gaus));
365  CLHEP::HepRotation y_smear_out_accelerator_plane(
366  accelerator_plane.cross(beam_center),
367  smear(
368  beam_bunch_zs.second * beam_angular_z_coefficient_hv.second, // central vertical angle shift
369  y_divergence, // vertical angle smear
370  Gaus));
371 
372  return y_smear_out_accelerator_plane * x_smear_in_accelerator_plane * beam_center;
373  };
374 
375  CLHEP::Hep3Vector beamA_vec = smear_beam_divergence(beamA_center,
378  CLHEP::Hep3Vector beamB_vec = smear_beam_divergence(beamB_center,
381 
382  if (m_verbosity)
383  {
384  cout << __PRETTY_FUNCTION__ << ": " << endl;
385  cout << "beamA_vec = " << beamA_vec << endl;
386  cout << "beamB_vec = " << beamB_vec << endl;
387  }
388 
389  assert(fabs(beamA_vec.mag2() - 1) < CLHEP::Hep3Vector::getTolerance());
390  assert(fabs(beamB_vec.mag2() - 1) < CLHEP::Hep3Vector::getTolerance());
391 
392  // apply minimal beam energy shift rotation and boost
393  CLHEP::Hep3Vector boost_axis = beamA_vec + beamB_vec;
394  if (boost_axis.mag2() > CLHEP::Hep3Vector::getTolerance())
395  {
396  //non-zero boost
397 
398  // split the boost to half for each beam for minimal beam energy shift
399  genevent->set_boost_beta_vector(0.5 * boost_axis);
400 
401  if (m_verbosity)
402  {
403  cout << __PRETTY_FUNCTION__ << ": non-zero boost " << endl;
404  }
405  } // if (cos_rotation_angle> CLHEP::Hep3Vector::getTolerance())
406  else
407  {
408  genevent->set_boost_beta_vector(CLHEP::Hep3Vector(0, 0, 0));
409  if (m_verbosity)
410  {
411  cout << __PRETTY_FUNCTION__ << ": zero boost " << endl;
412  }
413  }
414 
415  //rotation to collision to along z-axis with beamA pointing to +z
416  CLHEP::Hep3Vector beamDiffAxis = (beamA_vec - beamB_vec);
417  if (beamDiffAxis.mag2() < CLHEP::Hep3Vector::getTolerance())
418  {
419  cout << "PHHepMCGenHelper::HepMC2Lab_boost_rotation_translation - Fatal error -"
420  << "Beam A and Beam B are too close to each other in direction "
421  << "Please double check beam direction and divergence setting. "
422  << "beamA_vec = " << beamA_vec << ","
423  << "beamB_vec = " << beamB_vec << ","
424  << " Current setting:";
425 
426  Print();
427 
428  exit(1);
429  }
430 
431  beamDiffAxis = beamDiffAxis / beamDiffAxis.mag();
432  double cos_rotation_angle_to_z = beamDiffAxis.dot(z_axis);
433  if (m_verbosity)
434  {
435  cout << __PRETTY_FUNCTION__ << ": check rotation ";
436  cout << "cos_rotation_angle_to_z= " << cos_rotation_angle_to_z << endl;
437  }
438 
439  if (1 - cos_rotation_angle_to_z < CLHEP::Hep3Vector::getTolerance())
440  {
441  //no rotation
442  genevent->set_rotation_vector(z_axis);
443  genevent->set_rotation_angle(0);
444 
445  if (m_verbosity)
446  {
447  cout << __PRETTY_FUNCTION__ << ": no rotation " << endl;
448  }
449  }
450  else if (cos_rotation_angle_to_z + 1 < CLHEP::Hep3Vector::getTolerance())
451  {
452  // you got beam flipped
453  genevent->set_rotation_vector(CLHEP::Hep3Vector(0, 1, 0));
454  genevent->set_rotation_angle(M_PI);
455  if (m_verbosity)
456  {
457  cout << __PRETTY_FUNCTION__ << ": reverse beam direction " << endl;
458  }
459  }
460  else
461  {
462  // need a rotation
463  CLHEP::Hep3Vector rotation_axis = (beamA_vec - beamB_vec).cross(z_axis);
464  const double rotation_angle_to_z = -acos(cos_rotation_angle_to_z);
465 
466  genevent->set_rotation_vector(rotation_axis);
467  genevent->set_rotation_angle(rotation_angle_to_z);
468 
469  if (m_verbosity)
470  {
471  cout << __PRETTY_FUNCTION__ << ": has rotation " << endl;
472  }
473  } // if (boost_axis.mag2() > CLHEP::Hep3Vector::getTolerance())
474 
475  if (m_verbosity)
476  {
477  cout << __PRETTY_FUNCTION__ << ": final boost rotation shift of the collision" << endl;
478  genevent->identify();
479  }
480 }
481 
483 {
485  {
486  cout << __PRETTY_FUNCTION__ << " Fatal Error: "
487  << "m_use_beam_bunch_sim = " << m_use_beam_bunch_sim << ". Expect to simulate bunch interaction instead of applying vertex distributions"
488  << endl;
489  exit(1);
490  }
491  _vertex_func_x = x;
492  _vertex_func_y = y;
493  _vertex_func_z = z;
494  _vertex_func_t = t;
495  return;
496 }
497 
498 void PHHepMCGenHelper::set_vertex_distribution_mean(const double x, const double y, const double z, const double t)
499 {
501  {
502  cout << __PRETTY_FUNCTION__ << " Fatal Error: "
503  << "m_use_beam_bunch_sim = " << m_use_beam_bunch_sim << ". Expect to simulate bunch interaction instead of applying vertex distributions"
504  << endl;
505  exit(1);
506  }
507 
508  _vertex_x = x;
509  _vertex_y = y;
510  _vertex_z = z;
511  _vertex_t = t;
512  return;
513 }
514 
515 void PHHepMCGenHelper::set_vertex_distribution_width(const double x, const double y, const double z, const double t)
516 {
518  {
519  cout << __PRETTY_FUNCTION__ << " Fatal Error: "
520  << "m_use_beam_bunch_sim = " << m_use_beam_bunch_sim << ". Expect to simulate bunch interaction instead of applying vertex distributions"
521  << endl;
522  exit(1);
523  }
524 
525  _vertex_width_x = x;
526  _vertex_width_y = y;
527  _vertex_width_z = z;
528  _vertex_width_t = t;
529  return;
530 }
531 
532 void PHHepMCGenHelper::set_beam_bunch_width(const std::vector<double> &beamA, const std::vector<double> &beamB)
533 {
534  if (not m_use_beam_bunch_sim)
535  {
536  cout << __PRETTY_FUNCTION__ << " Fatal Error: "
537  << "m_use_beam_bunch_sim = " << m_use_beam_bunch_sim << ". Expect not to simulate bunch interaction but applying vertex distributions"
538  << endl;
539  exit(1);
540  }
541 
542  m_beam_bunch_width.first = beamA;
543  m_beam_bunch_width.second = beamB;
544 }
545 
546 double PHHepMCGenHelper::smear(const double position,
547  const double width,
548  VTXFUNC dist) const
549 {
550  assert(width >= 0);
551 
552  double res = position;
553 
554  if (width == 0)
555  return res;
556 
557  if (dist == Uniform)
558  {
559  res = (position - width) + 2 * gsl_rng_uniform_pos(RandomGenerator) * width;
560  }
561  else if (dist == Gaus)
562  {
563  res = position + gsl_ran_gaussian(RandomGenerator, width);
564  }
565  else
566  {
567  cout << "PHHepMCGenHelper::smear - FATAL Error - unknown vertex function " << dist << endl;
568  exit(10);
569  }
570  return res;
571 }
572 
574 {
575  //allow copy of vertex distributions
576  helper_dest.use_beam_bunch_sim(false);
580 
581  //allow copy of bunch distributions
582  helper_dest.use_beam_bunch_sim(true);
584 
585  //final bunch settings
587 
588  helper_dest.set_beam_direction_theta_phi(
589  m_beam_direction_theta_phi.first.first,
590  m_beam_direction_theta_phi.first.second,
591  m_beam_direction_theta_phi.second.first,
592  m_beam_direction_theta_phi.second.second);
593  helper_dest.set_beam_angular_divergence_hv(
594  m_beam_angular_divergence_hv.first.first,
595  m_beam_angular_divergence_hv.first.second,
596  m_beam_angular_divergence_hv.second.first,
597  m_beam_angular_divergence_hv.second.second);
600  m_beam_angular_z_coefficient_hv.first.second,
601  m_beam_angular_z_coefficient_hv.second.first,
602  m_beam_angular_z_coefficient_hv.second.second);
603 
606  m_beam_angular_z_coefficient_hv.first.second,
607  m_beam_angular_z_coefficient_hv.second.first,
608  m_beam_angular_z_coefficient_hv.second.second);
609 
610  return;
611 }
612 
614 {
615  if (helper_dest)
616  CopySettings(*helper_dest);
617  else
618  {
619  cout << "PHHepMCGenHelper::CopySettings - fatal error - invalid input class helper_dest which is nullptr!" << endl;
620  exit(1);
621  }
622 }
623 
625 {
626  if (helper_src)
627  helper_src->CopySettings(this);
628  else
629  {
630  cout << "PHHepMCGenHelper::CopyHelperSettings - fatal error - invalid input class helper_src which is nullptr!" << endl;
631  exit(1);
632  }
633 }
634 
635 void PHHepMCGenHelper::Print(const std::string &/*what*/) const
636 {
637  static map<VTXFUNC, string> vtxfunc = {{VTXFUNC::Uniform, "Uniform"}, {VTXFUNC::Gaus, "Gaus"}};
638 
639  cout << "Vertex distribution width x: " << _vertex_width_x
640  << ", y: " << _vertex_width_y
641  << ", z: " << _vertex_width_z
642  << ", t: " << _vertex_width_t
643  << endl;
644 
645  cout << "Vertex distribution function x: " << vtxfunc[_vertex_func_x]
646  << ", y: " << vtxfunc[_vertex_func_y]
647  << ", z: " << vtxfunc[_vertex_func_z]
648  << ", t: " << vtxfunc[_vertex_func_t]
649  << endl;
650 
651  cout << "Beam direction: A theta-phi = " << m_beam_direction_theta_phi.first.first
652  << ", " << m_beam_direction_theta_phi.first.second << endl;
653  cout << "Beam direction: B theta-phi = " << m_beam_direction_theta_phi.second.first
654  << ", " << m_beam_direction_theta_phi.second.second << endl;
655 
656  cout << "Beam divergence: A X-Y = " << m_beam_angular_divergence_hv.first.first
657  << ", " << m_beam_angular_divergence_hv.first.second << endl;
658  cout << "Beam divergence: B X-Y = " << m_beam_angular_divergence_hv.second.first
659  << ", " << m_beam_angular_divergence_hv.second.second << endl;
660 
661  cout << "Beam angle shift as linear function of longitudinal vertex position : A X-Y = " << m_beam_angular_z_coefficient_hv.first.first
662  << ", " << m_beam_angular_z_coefficient_hv.first.second << endl;
663  cout << "Beam angle shift as linear function of longitudinal vertex position: B X-Y = " << m_beam_angular_z_coefficient_hv.second.first
664  << ", " << m_beam_angular_z_coefficient_hv.second.second << endl;
665 
666  cout << "m_use_beam_bunch_sim = " << m_use_beam_bunch_sim << endl;
667 
668  cout << "Beam bunch A width = ["
669  << m_beam_bunch_width.first[0] << ", " << m_beam_bunch_width.first[1] << ", " << m_beam_bunch_width.first[2] << "] cm" << endl;
670  cout << "Beam bunch B width = ["
671  << m_beam_bunch_width.second[0] << ", " << m_beam_bunch_width.second[1] << ", " << m_beam_bunch_width.second[2] << "] cm" << endl;
672 
673  return;
674 }