Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MakeActsGeometry.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file MakeActsGeometry.cc
1 
8 #include "MakeActsGeometry.h"
9 
10 #include <trackbase/TrkrDefs.h>
11 #include <trackbase/InttDefs.h>
12 #include <trackbase/MvtxDefs.h>
13 #include <trackbase/TpcDefs.h>
17 
18 #include <intt/CylinderGeomIntt.h>
19 
20 #include <mvtx/CylinderGeom_Mvtx.h>
21 
23 
25 
28 #include <g4detectors/PHG4CylinderGeom.h> // for PHG4CylinderGeom
30 
31 #include <phgeom/PHGeomUtility.h>
32 #include <phgeom/PHGeomIOTGeo.h>
33 #include <phgeom/PHGeomTGeo.h>
34 
36 #include <fun4all/Fun4AllServer.h>
37 
39 
40 #include <phool/PHCompositeNode.h>
41 #include <phool/PHDataNode.h>
42 #include <phool/PHNode.h>
43 #include <phool/PHNodeIterator.h>
44 #include <phool/PHObject.h>
45 #include <phool/getClass.h>
46 #include <phool/phool.h>
47 
55 
58 
59 #pragma GCC diagnostic push
60 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
61 #pragma GCC diagnostic ignored "-Wuninitialized"
63 #pragma GCC diagnostic pop
64 
67 
69 
74 
75 #include <TGeoManager.h>
76 #include <TMatrixT.h>
77 #include <TObject.h>
78 #include <TSystem.h>
79 #include <TVector3.h>
80 
81 #include <cmath>
82 #include <cstddef>
83 #include <cstdlib>
84 #include <iostream>
85 #include <map>
86 #include <memory>
87 #include <utility>
88 #include <vector>
89 #include <filesystem>
90 
91 namespace
92 {
94  TrackingVolumePtr find_volume_by_name( const Acts::TrackingVolume* master, const std::string& name )
95  {
96  // skip if name is not composite
97  if( master->volumeName().empty() || master->volumeName()[0] != '{' ) return nullptr;
98 
99  // loop over children
100  for( const auto& child:master->confinedVolumes()->arrayObjects() )
101  {
102  if( child->volumeName() == name ) return child;
103  else if( auto found = find_volume_by_name( child.get(), name ) ) return found;
104  }
105 
106  // not found
107  return nullptr;
108  }
109 
110  template<class T> inline constexpr T square( const T& x ) { return x*x; }
111 
112  template<class T> inline T get_r( const T& x, const T&y ) { return std::sqrt( square(x) + square(y) ); }
113 
114 }
115 
117 : SubsysReco(name)
118 {
119  for ( int layer = 0; layer < 57; layer++)
120  {
121  m_misalignmentFactor.insert(std::make_pair(layer, 1.));
122  }
123 }
124 
126 {
127 
129 }
130 
132 {
134  findNode::getClass<PHG4TpcCylinderGeomContainer>(topNode, "CYLINDERCELLGEOM_SVTX");
135 
136  // Alignment Transformation declaration of instance - must be here to set initial alignment flag
137  AlignmentTransformation alignment_transformation;
138  alignment_transformation.createAlignmentTransformContainer(topNode);
139 
140  //set parameter for sampling probability distribution
141  if(mvtxParam){alignment_transformation.setMVTXParams(m_mvtxDevs);}
142  if(inttParam){alignment_transformation.setINTTParams(m_inttDevs);}
143  if(tpcParam){alignment_transformation.setTPCParams(m_tpcDevs);}
144  if(mmParam){alignment_transformation.setMMParams(m_mmDevs);}
145 
148 
151  trackingGeometry.tGeometry = m_tGeometry;
152  trackingGeometry.magField = m_magneticField;
153  trackingGeometry.getGeoContext() = m_geoCtxt; // set reference as plain geocontext
154  trackingGeometry.tpcSurfStepPhi = m_surfStepPhi;
155  trackingGeometry.tpcSurfStepZ = m_surfStepZ;
156 
157  // fill ActsSurfaceMap content
158  ActsSurfaceMaps surfMaps;
162  surfMaps.m_tGeoNodeMap = m_clusterNodeMap;
163 
164  // fill TPC volume ids
165  for( const auto& [hitsetid, surfaceVector]:m_clusterSurfaceMapTpcEdit )
166  for( const auto& surface:surfaceVector )
167  { surfMaps.m_tpcVolumeIds.insert( surface->geometryId().volume() ); }
168 
169  // fill Micromegas volume ids
170  for( const auto& [hitsetid, surface]:m_clusterSurfaceMapMmEdit )
171  { surfMaps.m_micromegasVolumeIds.insert( surface->geometryId().volume() ); }
172 
173  m_actsGeometry->setGeometry(trackingGeometry);
174  m_actsGeometry->setSurfMaps(surfMaps);
176  alignment_transformation.useInttSurveyGeometry(m_inttSurvey);
177  if(Verbosity() > 1)
178  {
179  alignment_transformation.verbosity();
180  }
181  alignment_transformation.createMap(topNode);
182 
183  for(auto& [layer, factor] : m_misalignmentFactor)
184  {
185  alignment_transformation.misalignmentFactor(layer, factor);
186  }
187 
188  // print
189  if( Verbosity() )
190  {
191  for( const auto& id:surfMaps.m_tpcVolumeIds )
192  { std::cout << "MakeActsGeometry::InitRun - TPC volume id: " << id << std::endl; }
193 
194  for( const auto& id:surfMaps.m_micromegasVolumeIds )
195  { std::cout << "MakeActsGeometry::InitRun - Micromegas volume id: " << id << std::endl; }
196  }
197 
199 }
200 
202 {
203 
205  // this also adds the micromegas surfaces
206  // Do this before anything else, so that the geometry is finalized
207 
208  if(getNodes(topNode) != Fun4AllReturnCodes::EVENT_OK)
210 
211  setPlanarSurfaceDivisions();//eshulga
212  // This should be done only on the first tracking pass, to avoid adding surfaces twice.
213  // There is a check for existing acts fake surfaces in editTPCGeometry
214  editTPCGeometry(topNode);
215 
217  if(Verbosity() > 3)
218  {
219  PHGeomUtility::ExportGeomtry(topNode, "sPHENIXActsGeom.root");
220  PHGeomUtility::ExportGeomtry(topNode, "sPHENIXActsGeom.gdml");
221  }
222 
225 
228 
230  //makeTGeoNodeMap(topNode);
231 
232 
233 
235 }
236 
238 {
239  // Because we reset and rebuild the geomNode, we do edits of the TPC geometry in the same module
240 
241  PHGeomTGeo *geomNode = PHGeomUtility::GetGeomTGeoNode(topNode, true);
242  assert(geomNode);
243 
245  if(geomNode->isValid())
246  {
247  geomNode->Reset();
248  }
249 
250  PHGeomIOTGeo *dstGeomIO = PHGeomUtility::GetGeomIOTGeoNode(topNode, false);
251  assert(dstGeomIO);
252  assert(dstGeomIO->isValid());
253 
254  TGeoManager *geoManager = dstGeomIO->ConstructTGeoManager();
255  geomNode->SetGeometry(geoManager);
256  assert(geoManager);
257 
258  if(TGeoManager::GetDefaultUnits() != TGeoManager::EDefaultUnits::kRootUnits)
259  {
260  std::cerr << "There is a potential unit mismatch in the ROOT geometry."
261  << " It is dangerous to continue and may lead to inconsistencies in the Acts geometry. Exiting."
262  << std::endl;
263  gSystem->Exit(1);
264  }
265 
266  TGeoVolume *World_vol = geoManager->GetTopVolume();
267 
268  // TPC geometry edits
269  //===============
270 
271  TGeoNode *tpc_envelope_node = nullptr;
272  TGeoNode *tpc_gas_north_node = nullptr;
273 
274  // find tpc north gas volume at path of World*/tpc_envelope*
275  if (Verbosity()> 3)
276  {
277  std::cout << "EditTPCGeometry - searching under volume: ";
278  World_vol->Print();
279  }
280  for (int i = 0; i < World_vol->GetNdaughters(); i++)
281  {
282  TString node_name = World_vol->GetNode(i)->GetName();
283  if (node_name.BeginsWith("tpc_envelope"))
284  {
285  if (Verbosity())
286  std::cout << "EditTPCGeometry - found " << node_name << std::endl;
287 
288  tpc_envelope_node = World_vol->GetNode(i);
289  break;
290  }
291  }
292 
293  assert(tpc_envelope_node);
294 
295  // find tpc north gas volume at path of World*/tpc_envelope*/tpc_gas_north*
296  TGeoVolume *tpc_envelope_vol = tpc_envelope_node->GetVolume();
297  assert(tpc_envelope_vol);
298  if (Verbosity() > 3)
299  {
300  std::cout << "EditTPCGeometry - searching under volume: ";
301  tpc_envelope_vol->Print();
302  }
303 
304  for (int i = 0; i < tpc_envelope_vol->GetNdaughters(); i++)
305  {
306  TString node_name = tpc_envelope_vol->GetNode(i)->GetName();
307 
308  if (node_name.BeginsWith("tpc_gas_north"))
309  {
310  if (Verbosity())
311  std::cout << "EditTPCGeometry - found " << node_name << std::endl;
312 
313  tpc_gas_north_node = tpc_envelope_vol->GetNode(i);
314  break;
315  }
316  }
317 
318  assert(tpc_gas_north_node);
319  TGeoVolume *tpc_gas_north_vol = tpc_gas_north_node->GetVolume();
320  assert(tpc_gas_north_vol);
321 
322  int nfakesurfaces = 0;
323  for(int i=0; i<tpc_gas_north_vol->GetNdaughters(); i++)
324  {
325  TString node_name = tpc_gas_north_vol->GetNode(i)->GetName();
326  if(node_name.BeginsWith("tpc_gas_measurement_"))
327  { nfakesurfaces++; }
328  }
329 
332  if(nfakesurfaces > 0)
333  { return; }
334 
335  if (Verbosity() > 3)
336  {
337  std::cout << "EditTPCGeometry - gas volume: ";
338  tpc_gas_north_vol->Print();
339  }
340 
341  // adds surfaces to the underlying volume, so both north and south placements get them
342  addActsTpcSurfaces(tpc_gas_north_vol, geoManager);
343 
344  // done
345  geoManager->CloseGeometry();
346 
347  // save the edited geometry to DST persistent IO node for downstream DST files
349 
350 }
351 
352 void MakeActsGeometry::addActsTpcSurfaces(TGeoVolume *tpc_gas_vol,
353  TGeoManager *geoManager)
354 {
355  TGeoMedium *tpc_gas_medium = tpc_gas_vol->GetMedium();
356  assert(tpc_gas_medium);
357 
358  // printout
359  std::cout << "MakeActsGeometry::addActsTpcSurfaces - m_nSurfPhi: " << m_nSurfPhi << std::endl;
360 
361  TGeoVolume *tpc_gas_measurement_vol[m_nTpcLayers];
362  double tan_half_phi = tan(m_surfStepPhi / 2.0);
363  int copy = 0;
364  for(unsigned int ilayer = 0; ilayer < m_nTpcLayers; ++ilayer)
365  {
366  // make a box for this layer
367  char bname[500];
368  sprintf(bname,"tpc_gas_measurement_%u",ilayer);
369 
370  // Because we use a box, not a section of a cylinder, we need this to prevent overlaps
371  // set the nominal r*phi dimension of the box so they just touch at the inner edge when placed
372  double box_r_phi = 2.0 * tan_half_phi *
373  (m_layerRadius[ilayer] - m_layerThickness[ilayer] / 2.0);
374 
375 
376  tpc_gas_measurement_vol[ilayer] = geoManager->MakeBox(bname, tpc_gas_medium,
378  box_r_phi*half_width_clearance_phi,
380 
381  tpc_gas_measurement_vol[ilayer]->SetLineColor(kBlack);
382  tpc_gas_measurement_vol[ilayer]->SetFillColor(kYellow);
383  tpc_gas_measurement_vol[ilayer]->SetVisibility(kTRUE);
384 
385  if(Verbosity() > 3)
386  {
387  std::cout << " Made box for layer " << ilayer
388  << " with dx " << m_layerThickness[ilayer] << " dy "
389  << box_r_phi << " ref arc "
390  << m_surfStepPhi * m_layerRadius[ilayer] << " dz "
391  << m_surfStepZ << std::endl;
392  tpc_gas_measurement_vol[ilayer]->Print();
393  tpc_gas_measurement_vol[ilayer]->CheckOverlaps();
394  }
395 
396  for (unsigned int iz = 0; iz < m_nSurfZ; ++iz)
397  {
398  // The (half) tpc gas volume is 105.5 cm long and is symmetric around (x,y,z) = (0,0,0) in its frame
399  double z_center = 0.0;
400 
401  for (unsigned int imod = 0; imod < m_nTpcModulesPerLayer; ++imod)
402  {
403  for (unsigned int iphi = 0; iphi < m_nSurfPhi; ++iphi)
404  {
405 
406  double min_phi = m_modulePhiStart +
407  (double) imod * m_moduleStepPhi +
408  (double) iphi * m_surfStepPhi;
409  double phi_center = min_phi + m_surfStepPhi / 2.0;
410  double phi_center_degrees = phi_center * 180.0 / M_PI;
411 
412  // place copies of the gas volume to fill up the layer
413 
414  double x_center = m_layerRadius[ilayer] * cos(phi_center);
415  double y_center = m_layerRadius[ilayer] * sin(phi_center);
416 
417  char rot_name[500];
418  sprintf(rot_name,"tpc_gas_rotation_%i", copy);
419  TGeoCombiTrans *tpc_gas_measurement_location
420  = new TGeoCombiTrans(x_center, y_center, z_center,
421  new TGeoRotation(rot_name,
422  phi_center_degrees,
423  0, 0));
424 
425  tpc_gas_vol->AddNode(tpc_gas_measurement_vol[ilayer],
426  copy, tpc_gas_measurement_location);
427 
428  copy++;
429  if(Verbosity() > 3 )
430  {
431 
432  std::cout << "Box center : ("<<x_center<<", " <<y_center
433  << ", " << z_center << ")" << " and in rphiz "
434  << sqrt(x_center*x_center+y_center*y_center)
435  << ", " << atan2(y_center,x_center) << ", "
436  << z_center << std::endl;
437  std::cout << "Box dimensions " <<m_layerThickness[ilayer] *half_width_clearance_thick
438  <<" , " << box_r_phi/(m_layerRadius[ilayer]-m_layerThickness[ilayer]/2.) * half_width_clearance_phi
439  << ", " << m_surfStepZ*half_width_clearance_z << " and in xyz "
440  << m_layerThickness[ilayer]*half_width_clearance_thick*cos(box_r_phi/(m_layerRadius[ilayer]-m_layerThickness[ilayer]/2.)*half_width_clearance_phi) << ", "
441  << m_layerThickness[ilayer]*half_width_clearance_thick*sin(box_r_phi/(m_layerRadius[ilayer]-m_layerThickness[ilayer]/2.)*half_width_clearance_phi) << ", "
442  <<m_surfStepZ*half_width_clearance_z<<std::endl;
443  }
444  }
445  }
446  }
447  }
448  }
449 
454 {
455 
456  // define int argc and char* argv to provide options to processGeometry
457  const int argc = 20;
458  char* arg[argc];
459  m_magFieldRescale = 1;
460  // if(Verbosity() > 0)
461  std::cout << PHWHERE << "Magnetic field " << m_magField
462  << " with rescale " << m_magFieldRescale << std::endl;
463 
464  std::string responseFile, materialFile;
465  setMaterialResponseFile(responseFile, materialFile);
466 
467  // Response file contains arguments necessary for geometry building
468  std::ostringstream fld;
469  fld.str("");
470  fld<<"0:0:"<<m_magField;
471  std::string argstr[argc]{
472  "-n1",
473  "--geo-tgeo-jsonconfig", responseFile,
474  "--mat-input-type","file",
475  "--mat-input-file", materialFile,
476  "--bf-constant-tesla",fld.str().c_str(),
477  "--bf-bscalor"};
478 
479  argstr[9] = std::to_string(m_magFieldRescale);
480 
481 
483  if(m_magField.find(".root") != std::string::npos)
484  {
485 
486  char *calibrationsroot = getenv("CALIBRATIONROOT");
487  m_magField = "sphenix3dtrackingmapxyz.root";
488 
489  if (calibrationsroot != nullptr)
490  {
491  m_magField = std::string(calibrationsroot) + std::string("/Field/Map/") + m_magField;
492  }
493 
494  m_magField = CDBInterface::instance()->getUrl("FIELDMAPTRACKING", m_magField);
495 
496  argstr[7] = "--bf-map-file";
497  argstr[8] = m_magField;
498  argstr[9]= "--bf-map-tree";
499  argstr[10] = "fieldmap";
500  argstr[11] = "--bf-map-lengthscale-mm";
501  argstr[12] = "10";
502  argstr[13] = "--bf-map-fieldscale-tesla";
503  argstr[14] = std::to_string(m_magFieldRescale);
504 
505  }
506 
507  // if(Verbosity() > 0)
508  std::cout << "Mag field now " << m_magField << " with rescale "
509  << m_magFieldRescale << std::endl;
510 
511  // Set vector of chars to arguments needed
512  for (int i = 0; i < argc; ++i)
513  {
514  if(Verbosity() > 1)
515  std::cout << argstr[i] << ", ";
516  // need a copy, since .c_str() returns a const char * and process geometry will not take a const
517  arg[i] = strdup(argstr[i].c_str());
518  }
519 
520  // We replicate the relevant functionality of
521  //acts/Examples/Run/Common/src/GeometryExampleBase::ProcessGeometry() in MakeActsGeometry()
522  // so we get access to the results. The layer builder magically gets the TGeoManager
523 
524  makeGeometry(argc, arg, m_detector);
525 
526  for(int i=0; i<argc; i++)
527  free(arg[i]);
528 
529 }
531  std::string& materialFile)
532 {
533 
534  responseFile = "tgeo-sphenix-mms.json";
535  materialFile = "sphenix-mm-material.json";
537  std::ifstream file;
538 
539  file.open(responseFile);
540  if(!file.is_open())
541  {
542  std::cout << responseFile
543  << " not found locally, use repo version"
544  << std::endl;
545  char *offline_main = getenv("OFFLINE_MAIN");
546  assert(offline_main);
547  responseFile = std::string(offline_main) +
548  ("/share/tgeo-sphenix-mms.json");
549  }
550 
551  file.open(materialFile);
552  if(!file.is_open())
553  {
554  std::cout << materialFile
555  << " not found locally, use repo version"
556  << std::endl;
557  const char* calibrationroot = getenv("CALIBRATIONROOT");
558  assert(calibrationroot);
559  materialFile = std::string(calibrationroot) +
560  ("/ACTS/sphenix-mm-material.json");
561  }
562 
563  if(Verbosity() > -1)
564  {
565  std::cout << "using Acts material file : " << materialFile
566  << std::endl;
567  std::cout << "Using Acts TGeoResponse file : " << responseFile
568  << std::endl;
569  }
570 
571  return;
572 
573 }
574 void MakeActsGeometry::makeGeometry(int argc, char* argv[],
576 {
577 
579  boost::program_options::options_description desc;
583 
585  detector.addOptions(desc);
586  auto vm = ActsExamples::Options::parse(desc, argc, argv);
587 
589  auto geometry = build(vm, detector);
591 
592  m_tGeometry = geometry.first;
593  if(m_useField)
595  else
596  { m_magneticField = nullptr; }
597 
599 
600  unpackVolumes();
601 
602  return;
603 }
604 
605 
606 std::pair<std::shared_ptr<const Acts::TrackingGeometry>,
607  std::vector<std::shared_ptr<ActsExamples::IContextDecorator>>>
608 MakeActsGeometry::build(const boost::program_options::variables_map& vm,
610  // Material decoration
611  std::shared_ptr<const Acts::IMaterialDecorator> matDeco = nullptr;
612 
613  // Retrieve the filename
614  auto fileName = vm["mat-input-file"].template as<std::string>();
615  // json or root based decorator
616  if (fileName.find(".json") != std::string::npos ||
617  fileName.find(".cbor") != std::string::npos)
618  {
619  // Set up the converter first
620  Acts::MaterialMapJsonConverter::Config jsonGeoConvConfig;
621  // Set up the json-based decorator
622  matDeco = std::make_shared<const Acts::JsonMaterialDecorator>(
623  jsonGeoConvConfig, fileName, Acts::Logging::FATAL);
624  }
625  else
626  {
627  matDeco = std::make_shared<const Acts::MaterialWiper>();
628  }
629 
631 
633 
634  config.fileName = vm["geo-tgeo-filename"].as<std::string>();
635 
639 
640  const auto path = vm["geo-tgeo-jsonconfig"].template as<std::string>();
641 
643 
645  return detector.m_detector.finalize(config, matDeco);
646  }
647 
650  if (path.empty()) {
651  std::cout << "There is no acts geometry response file loaded. Cannot build, exiting"
652  << std::endl;
653  exit(1);
654  }
655 
656  nlohmann::json djson;
657  std::ifstream infile(path, std::ifstream::in | std::ifstream::binary);
658  infile >> djson;
659 
660  config.unitScalor = djson["geo-tgeo-unit-scalor"];
661 
662  config.buildBeamPipe = djson["geo-tgeo-build-beampipe"];
663  if (config.buildBeamPipe) {
664  const auto beamPipeParameters =
665  djson["geo-tgeo-beampipe-parameters"].get<std::array<double, 3>>();
666  config.beamPipeRadius = beamPipeParameters[0];
667  config.beamPipeHalflengthZ = beamPipeParameters[1];
668  config.beamPipeLayerThickness = beamPipeParameters[2];
669  }
670 
671  // Fill nested volume configs
672  for (const auto& volume : djson["Volumes"]) {
673  auto& vol = config.volumes.emplace_back();
674  vol = volume;
675  }
676 }
677 
679 {
682  auto vol = m_tGeometry->highestTrackingVolume();
683 
684  if(Verbosity() > 3 )
685  {
686  std::cout << "MakeActsGeometry::unpackVolumes - top volume: " << vol->volumeName() << std::endl;
687  std::cout << "Before: Mvtx: m_clusterSurfaceMapSilicon size " << m_clusterSurfaceMapSilicon.size() << std::endl;
688  std::cout << "Before: m_clusterSurfaceMapTpc size " << m_clusterSurfaceMapTpcEdit.size() << std::endl;
689  }
690  {
691  // micromegas
692  auto mmBarrel = find_volume_by_name( vol, "MICROMEGAS::Barrel" );
693  assert( mmBarrel );
694  makeMmMapPairs(mmBarrel);
695  }
696  {
697  // MVTX
698  auto mvtxBarrel = find_volume_by_name( vol, "MVTX::Barrel" );
699  assert( mvtxBarrel );
700  makeMvtxMapPairs(mvtxBarrel);
701  if(Verbosity() > 3)
702  { std::cout << "After: Mvtx: m_clusterSurfaceMapSilicon size " << m_clusterSurfaceMapSilicon.size() << std::endl; }
703  }
704 
705  {
706  // INTT
707  if(Verbosity() > 3)
708  { std::cout << "Before: INTT: m_clusterSurfaceMapSilicon size " << m_clusterSurfaceMapSilicon.size() << std::endl; }
709  auto inttBarrel = find_volume_by_name( vol, "Silicon::Barrel" );
710  assert( inttBarrel );
711  makeInttMapPairs(inttBarrel);
712  if(Verbosity() > 3)
713  { std::cout << "After: INTT: m_clusterSurfaceMapSilicon size " << m_clusterSurfaceMapSilicon.size() << std::endl; }
714  }
715 
716  {
717  // TPC
718  auto tpcBarrel = find_volume_by_name( vol, "TPC::Barrel" );
719  assert( tpcBarrel );
720  makeTpcMapPairs(tpcBarrel);
721  if(Verbosity() > 3)
722  { std::cout << "After: m_clusterSurfaceMapTpc size " << m_clusterSurfaceMapTpcEdit.size() << std::endl; }
723  }
724 
725  return;
726 }
727 
729 {
730  if(Verbosity() > 10)
731  { std::cout << "MakeActsGeometry::makeTpcMapPairs - tpcVolume: " << tpcVolume->volumeName() << std::endl; }
732 
733  auto tpcLayerArray = tpcVolume->confinedLayers();
734  auto tpcLayerVector = tpcLayerArray->arrayObjects();
735 
737  for(unsigned int i = 0; i < tpcLayerVector.size(); i++)
738  {
739  auto surfaceArray = tpcLayerVector.at(i)->surfaceArray();
740  if(surfaceArray == NULL){
741  continue;
742  }
745  auto surfaceVector = surfaceArray->surfaces();
746  for( unsigned int j = 0; j < surfaceVector.size(); j++)
747  {
748  auto surf = surfaceVector.at(j)->getSharedPtr();
749  auto vec3d = surf->center(m_geoCtxt);
750 
752  std::vector<double> world_center = {vec3d(0) / 10.0,
753  vec3d(1) / 10.0,
754  vec3d(2) / 10.0};
755 
757  unsigned int layer = TrkrDefs::getLayer(hitsetkey);
758 
761  //std::map<TrkrDefs::hitsetkey, std::vector<Surface>>::iterator mapIter;
762  std::map<unsigned int, std::vector<Surface>>::iterator mapIter;
763  //mapIter = m_clusterSurfaceMapTpcEdit.find(hitsetkey);
764  mapIter = m_clusterSurfaceMapTpcEdit.find(layer);
765 
766  if(mapIter != m_clusterSurfaceMapTpcEdit.end())
767  {
768  mapIter->second.push_back(surf);
769  }
770  else
771  {
773  std::vector<Surface> dumvec;
774  dumvec.push_back(surf);
775  std::pair<unsigned int, std::vector<Surface>> tmp =
776  std::make_pair(layer, dumvec);
777  m_clusterSurfaceMapTpcEdit.insert(tmp);
778  }
779 
780  }
781  }
782 
783 }
784 
785 //____________________________________________________________________________________________
787 {
788  if(Verbosity())
789  { std::cout << "MakeActsGeometry::makeMmMapPairs - mmVolume: " << mmVolume->volumeName() << std::endl; }
790  const auto mmLayerArray = mmVolume->confinedLayers();
791  const auto mmLayerVector = mmLayerArray->arrayObjects();
792 
794  for(unsigned int i = 0; i < mmLayerVector.size(); i++)
795  {
796  auto surfaceArray = mmLayerVector.at(i)->surfaceArray();
797  if(!surfaceArray) continue;
798 
801  const auto surfaceVector = surfaceArray->surfaces();
802 
803  for( unsigned int j = 0; j < surfaceVector.size(); j++)
804  {
805  auto surface = surfaceVector.at(j)->getSharedPtr();
806  auto vec3d = surface->center(m_geoCtxt);
807 
809  TVector3 world_center(
810  vec3d(0)/Acts::UnitConstants::cm,
811  vec3d(1)/Acts::UnitConstants::cm,
812  vec3d(2)/Acts::UnitConstants::cm
813  );
814 
815  // get relevant layer
816  int layer = -1;
817  CylinderGeomMicromegas* layergeom = nullptr;
818  const auto range = m_geomContainerMicromegas->get_begin_end();
819  double delta_r_min = -1;
820  for( auto iter = range.first; iter != range.second; ++iter )
821  {
822  auto this_layergeom = static_cast<CylinderGeomMicromegas*>( iter->second );
823  const double delta_r = std::abs( this_layergeom->get_radius() - get_r( world_center.x(), world_center.y() ) );
824  if( delta_r_min < 0 || delta_r < delta_r_min )
825  {
826  layer = iter->first;
827  layergeom = this_layergeom;
828  delta_r_min = delta_r;
829  }
830  }
831 
832  if( !layergeom )
833  {
834  std::cout << "MakeActsGeometry::makeMmMapPairs - could not file CylinderGeomMicromegas matching ACTS surface" << std::endl;
835  continue;
836  }
837 
838  // get matching tile
839  int tileid = layergeom->find_tile_cylindrical( world_center );
840  if( tileid < 0 )
841  {
842  std::cout << "MakeActsGeometry::makeMmMapPairs - could not file Micromegas tile matching ACTS surface" << std::endl;
843  continue;
844  }
845 
846  if( Verbosity() )
847  { std::cout << "MakeActsGeometry::makeMmMapPairs - layer: " << layer << " tileid: " << tileid << std::endl; }
848 
849  // get segmentation type
850  const auto segmentation_type = layergeom->get_segmentation_type();
851 
852  // create hitset key and insert surface in map
853  const auto hitsetkey = MicromegasDefs::genHitSetKey(layer, segmentation_type, tileid);
854  const auto [iter, inserted] = m_clusterSurfaceMapMmEdit.insert( std::make_pair( hitsetkey, surface ) );
855  assert( inserted );
856  }
857  }
858 }
859 
861 {
862 
863  if(Verbosity() > 10)
864  { std::cout << "MakeActsGeometry::makeInttMapPairs - inttVolume: " << inttVolume->volumeName() << std::endl; }
865 
866  auto inttLayerArray = inttVolume->confinedLayers();
867 
868  auto inttLayerVector = inttLayerArray->arrayObjects();
869  // inttLayerVector is a std::vector<LayerPtr>
870  for (unsigned int i = 0; i < inttLayerVector.size(); i++)
871  {
872  // Get the ACTS::SurfaceArray from each INTT LayerPtr being iterated over
873  auto surfaceArray = inttLayerVector.at(i)->surfaceArray();
874  if (surfaceArray == NULL)
875  continue;
876 
877  // surfaceVector is an Acts::SurfaceVector, vector of surfaces
878  auto surfaceVector = surfaceArray->surfaces();
879 
880  for (unsigned int j = 0; j < surfaceVector.size(); j++)
881  {
882  auto surf = surfaceVector.at(j)->getSharedPtr();
883  auto vec3d = surf->center(m_geoCtxt);
884 
885  double ref_rad[4] = {7.188, 7.732, 9.680, 10.262};
886 
887  std::vector<double> world_center = {vec3d(0) / 10.0, vec3d(1) / 10.0, vec3d(2) / 10.0}; // convert from mm to cm
888 
892  double layer_rad = sqrt(pow(world_center[0], 2) + pow(world_center[1], 2));
893 
894  unsigned int layer = 0;
895  for (unsigned int i = 0; i < 4; ++i)
896  {
897  if (fabs(layer_rad - ref_rad[i]) < 0.1)
898  layer = i + 3;
899  }
900 
902 
903  // Add this surface to the map
904  std::pair<TrkrDefs::hitsetkey, Surface> tmp = make_pair(hitsetkey, surf);
905  m_clusterSurfaceMapSilicon.insert(tmp);
906 
907  if (Verbosity() > 10)
908  {
909  // check it is in there
910  unsigned int ladderPhi = InttDefs::getLadderPhiId(hitsetkey);
911  unsigned int ladderZ = InttDefs::getLadderZId(hitsetkey);
912 
913  std::cout << "Layer radius " << layer_rad << " layer " << layer << " ladderPhi " << ladderPhi << " ladderZ " << ladderZ << " hitsetkey " << hitsetkey
914  << " recover surface from m_clusterSurfaceMapSilicon " << std::endl;
915  std::cout << " surface type " << surf->type() << std::endl;
916  auto assoc_layer = surf->associatedLayer();
917  std::cout << std::endl
918  << " Layer type " << assoc_layer->layerType() << std::endl;
919 
920  auto assoc_det_element = surf->associatedDetectorElement();
921  if (assoc_det_element != nullptr)
922  {
923  std::cout << " Associated detElement has non-null pointer "
924  << assoc_det_element << std::endl;
925  std::cout << std::endl
926  << " Associated detElement found, thickness = "
927  << assoc_det_element->thickness() << std::endl;
928  }
929  else
930  std::cout << std::endl
931  << " Associated detElement is nullptr " << std::endl;
932  }
933  }
934  }
935 
936 }
937 
939 {
940 
941  if(Verbosity() > 10)
942  { std::cout << "MakeActsGeometry::makeMvtxMapPairs - mvtxVolume: " << mvtxVolume->volumeName() << std::endl; }
943 
944  // Now get the LayerArrays corresponding to each volume
945  auto mvtxBarrelLayerArray = mvtxVolume->confinedLayers(); // the barrel is all we care about
946 
947  // This is a BinnedArray<LayerPtr>, but we care only about the sensitive surfaces
948  auto mvtxLayerVector1 = mvtxBarrelLayerArray->arrayObjects(); // the barrel is all we care about
949 
950  // mvtxLayerVector has size 3, but only index 1 has any surfaces since the clayersplits option was removed
951  // the layer number has to be deduced from the radius
952  for (unsigned int i = 0; i < mvtxLayerVector1.size(); ++i)
953  {
954  // Get the Acts::SurfaceArray from each MVTX LayerPtr being iterated over
955  auto surfaceArray = mvtxLayerVector1.at(i)->surfaceArray();
956  if (surfaceArray == NULL)
957  continue;
958 
959  double ref_rad[3] = {2.556, 3.359, 4.134};
960 
961  // surfaceVector is an Acts::SurfaceVector, vector of surfaces
962  //std::vector<const Surface*>
963  auto surfaceVector = surfaceArray->surfaces();
964  for (unsigned int j = 0; j < surfaceVector.size(); j++)
965  {
966  auto surf = surfaceVector.at(j)->getSharedPtr();
967  auto vec3d = surf->center(m_geoCtxt);
968  std::vector<double> world_center = {vec3d(0) / 10.0, vec3d(1) / 10.0, vec3d(2) / 10.0}; // convert from mm to cm
969  double layer_rad = sqrt(pow(world_center[0], 2) + pow(world_center[1], 2));
970  unsigned int layer = 0;
971  for (unsigned int i = 0; i < 3; ++i)
972  {
973  if (fabs(layer_rad - ref_rad[i]) < 0.1)
974  layer = i;
975  }
976 
978 
979  // Add this surface to the map
980  std::pair<TrkrDefs::hitsetkey, Surface> tmp = make_pair(hitsetkey, surf);
981 
982  m_clusterSurfaceMapSilicon.insert(tmp);
983 
984  if (Verbosity() > 10)
985  {
986  unsigned int stave = MvtxDefs::getStaveId(hitsetkey);
987  unsigned int chip = MvtxDefs::getChipId(hitsetkey);
988 
989  // check it is in there
990  std::cout << "Layer radius " << layer_rad << " Layer "
991  << layer << " stave " << stave << " chip " << chip
992  << " recover surface from m_clusterSurfaceMapSilicon "
993  << std::endl;
994 
995  std::map<TrkrDefs::hitsetkey, Surface>::iterator surf_iter = m_clusterSurfaceMapSilicon.find(hitsetkey);
996  std::cout << " surface type " << surf_iter->second->type()
997  << std::endl;
998  auto assoc_layer = surf->associatedLayer();
999  std::cout << std::endl << " Layer type "
1000  << assoc_layer->layerType() << std::endl;
1001 
1002  auto assoc_det_element = surf->associatedDetectorElement();
1003  if (assoc_det_element != nullptr)
1004  {
1005  std::cout << " Associated detElement has non-null pointer "
1006  << assoc_det_element << std::endl;
1007  std::cout << std::endl
1008  << " Associated detElement found, thickness = "
1009  << assoc_det_element->thickness() << std::endl;
1010  }
1011  else
1012  std::cout << std::endl
1013  << " Associated detElement is nullptr " << std::endl;
1014  }
1015  }
1016  }
1017 }
1018 
1020 {
1021  // Look up TPC surface index values from world position of surface center
1022  // layer
1023  unsigned int layer = 999;
1024  double layer_rad = sqrt(pow(world[0],2) + pow(world[1],2));
1025  for(unsigned int ilayer=0;ilayer<m_nTpcLayers;++ilayer)
1026  {
1027  double tpc_ref_radius_low =
1028  m_layerRadius[ilayer] - m_layerThickness[ilayer] / 2.0;
1029  double tpc_ref_radius_high =
1030  m_layerRadius[ilayer] + m_layerThickness[ilayer] / 2.0;
1031  if(layer_rad >= tpc_ref_radius_low && layer_rad < tpc_ref_radius_high)
1032  {
1033  layer = ilayer;
1034  break;
1035  }
1036  }
1037 
1038  if(layer >= m_nTpcLayers)
1039  {
1040  std::cout << PHWHERE
1041  << "Error: undefined layer, do nothing world = "
1042  << world[0] << " " << world[1] << " " << world[2]
1043  << " layer " << layer << std::endl;
1045  }
1046 
1047  layer += 7;
1048 
1049  // side - from world z sign
1050  unsigned int side;
1051  if(world[2] < 0)
1052  side = 0;
1053  else
1054  side = 1;
1055 
1056  // readout module
1057  unsigned int readout_mod = 999;
1058  double phi_world = atan2(world[1], world[0]);
1059  for(unsigned int imod=0; imod<m_nTpcModulesPerLayer; ++imod)
1060  {
1061  double min_phi = m_modulePhiStart + (double) imod * m_moduleStepPhi;
1062  double max_phi = m_modulePhiStart + (double) (imod+1) * m_moduleStepPhi;
1063  if(phi_world >=min_phi && phi_world < max_phi)
1064  {
1065  readout_mod = imod;
1066  break;
1067  }
1068  }
1069  if(readout_mod >= m_nTpcModulesPerLayer)
1070  {
1071  std::cout << PHWHERE
1072  << "Error: readout_mod is undefined, do nothing phi_world = "
1073  << phi_world << std::endl;
1075  }
1076 
1077  TrkrDefs::hitsetkey hitset_key = TpcDefs::genHitSetKey(layer, readout_mod, side);
1078  if(Verbosity() > 3)
1079  if(layer == 30)
1080  std::cout << " world = " << world[0] << " " << world[1]
1081  << " " << world[2] << " phi_world "
1082  << phi_world*180/M_PI << " layer " << layer
1083  << " readout_mod " << readout_mod << " side " << side
1084  << " hitsetkey " << hitset_key<< std::endl;
1085 
1086  return hitset_key;
1087 }
1088 
1090 {
1091  // Look up the MVTX sensor index values from the world position of the surface center
1092 
1093  CylinderGeom_Mvtx *layergeom = dynamic_cast<CylinderGeom_Mvtx *>(m_geomContainerMvtx->GetLayerGeom(layer));
1094  if (!layergeom)
1095  {
1096  std::cout << PHWHERE << "Did not get layergeom for layer "
1097  << layer << std::endl;
1098  return 0;
1099  }
1100 
1101  unsigned int stave = 0;
1102  unsigned int chip = 0;
1103  layergeom->get_sensor_indices_from_world_coords(world, stave, chip);
1104 
1105  unsigned int strobe = 0;
1106  TrkrDefs::hitsetkey mvtx_hitsetkey = MvtxDefs::genHitSetKey(layer, stave, chip, strobe);
1107 
1108  return mvtx_hitsetkey;
1109 }
1110 
1112 {
1113  // Look up the INTT sensor index values from the world position of the surface center
1114 
1115  CylinderGeomIntt *layergeom = dynamic_cast<CylinderGeomIntt *>(m_geomContainerIntt->GetLayerGeom(layer));
1116  if (!layergeom)
1117  {
1118  std::cout << PHWHERE << "Did not get layergeom for layer "
1119  << layer << std::endl;
1120  return 0;
1121  }
1122 
1123  double location[3] = {world[0], world[1], world[2]};
1124  int segment_z_bin = 0;
1125  int segment_phi_bin = 0;
1126  layergeom->find_indices_from_segment_center(segment_z_bin,
1127  segment_phi_bin, location);
1128 
1129  int crossing = 0;
1130  TrkrDefs::hitsetkey intt_hitsetkey = InttDefs::genHitSetKey(layer, segment_z_bin, segment_phi_bin, crossing);
1131 
1132  return intt_hitsetkey;
1133 }
1134 
1135 
1136 // void MakeActsGeometry::makeTGeoNodeMap(PHCompositeNode * /*topNode*/)
1137 // {
1138 // // This is just a diagnostic method
1139 // // it lets you list all of the nodes by setting print_sensors = true
1140 //
1141 // if (!m_geoManager)
1142 // {
1143 // std::cout << PHWHERE << " Did not find TGeoManager, quit! " << std::endl;
1144 // return;
1145 // }
1146 // TGeoVolume *topVol = m_geoManager->GetTopVolume();
1147 // TObjArray *nodeArray = topVol->GetNodes();
1148 //
1149 // TIter iObj(nodeArray);
1150 // while (TObject *obj = iObj())
1151 // {
1152 // TGeoNode *node = dynamic_cast<TGeoNode *>(obj);
1153 // std::string node_str = node->GetName();
1154 //
1155 // std::string mvtx("MVTX_Wrapper");
1156 // std::string intt("ladder");
1157 // std::string intt_ext("ladderext");
1158 // std::string tpc("tpc_envelope");
1159 // std::string micromegas("MICROMEGAS_55");
1160 //
1161 // if (node_str.compare(0, mvtx.length(), mvtx) == 0) // is it in the MVTX?
1162 // {
1163 // if (Verbosity() > 2)
1164 // std::cout << " node " << node->GetName() << " is the MVTX wrapper"
1165 // << std::endl;
1166 //
1167 // /// The Mvtx has an additional wrapper that needs to be unpacked
1168 // TObjArray *mvtxArray = node->GetNodes();
1169 // TIter mvtxObj(mvtxArray);
1170 // while(TObject *mvtx = mvtxObj())
1171 // {
1172 // TGeoNode *mvtxNode = dynamic_cast<TGeoNode *>(mvtx);
1173 // if(Verbosity() > 2)
1174 // std::cout << "mvtx node name is " << mvtxNode->GetName()
1175 // << std::endl;
1176 // std::string mvtxav1("av_1");
1177 // std::string mvtxNodeName = mvtxNode->GetName();
1178 //
1179 // /// We only want the av_1 nodes
1180 // if(mvtxNodeName.compare(0, mvtxav1.length(), mvtxav1) == 0)
1181 // getMvtxKeyFromNode(mvtxNode);
1182 // }
1183 // }
1184 // else if (node_str.compare(0, intt.length(), intt) == 0) // is it in the INTT?
1185 // {
1186 // // We do not want the "ladderext" nodes
1187 // if (node_str.compare(0, intt_ext.length(), intt_ext) == 0)
1188 // continue;
1189 //
1190 // if (Verbosity() > 2)
1191 // std::cout << " node " << node->GetName() << " is in the INTT"
1192 // << std::endl;
1193 // getInttKeyFromNode(node);
1194 // }
1195 // /// Put placeholders for the TPC and MMs. Because we modify the geometry
1196 // /// within TGeoVolume, we don't need a mapping to the TGeoNode
1197 // else if (node_str.compare(0, tpc.length(), tpc) == 0) // is it in the TPC?
1198 // {
1199 // if(Verbosity() > 2)
1200 // std::cout << " node " << node->GetName()
1201 // << " is in the TPC " << std::endl;
1202 // }
1203 // else if (node_str.compare(0, micromegas.length(), micromegas) == 0) // is it in the Micromegas?
1204 // {
1205 // if(Verbosity() > 2)
1206 // std::cout << " node " << node->GetName()
1207 // << " is in the MMs " << std::endl;
1208 // }
1209 // else
1210 // continue;
1211 //
1212 // bool print_sensor_paths = false; // normally false
1213 // if (print_sensor_paths)
1214 // {
1215 // // Descends the node tree to find the active silicon nodes - used for information only
1216 // std::cout << " Top Node is " << node->GetName() << " volume name is " << node->GetVolume()->GetName() << std::endl;
1217 //
1218 // int nmax_print = 20;
1219 // isActive(node, nmax_print);
1220 // }
1221 // }
1222 // }
1223 
1225 {
1226  int layer = -1; // sPHENIX layer number
1227  int itype = -1; // specifies inner (0) or outer (1) sensor
1228  int ladder_phi = -1; // copy number of ladder in phi
1229  int zposneg = -1; // specifies positive (1) or negative (0) z
1230  int ladder_z = -1; // 0-3, from most negative z to most positive
1231 
1232  std::string s = gnode->GetName();
1233  std::string delimiter = "_";
1234  std::string posz("posz");
1235  std::string negz("negz");
1236 
1237  size_t pos = 0;
1239 
1240  int counter = 0;
1241  while ((pos = s.find(delimiter)) != std::string::npos)
1242  {
1243  token = s.substr(0, pos);
1244 
1245  s.erase(0, pos + delimiter.length());
1246  if (counter == 1)
1247  layer = std::atoi(token.c_str()) + 3;
1248  if (counter == 2)
1249  itype = std::atoi(token.c_str());
1250  if (counter == 3)
1251  {
1252  ladder_phi = std::atoi(token.c_str());
1253  if (s.compare(0, negz.length(), negz) == 0) zposneg = 0;
1254  if (s.compare(0, posz.length(), posz) == 0) zposneg = 1;
1255  }
1256  counter++;
1257  }
1258 
1259  ladder_z = itype + zposneg * 2;
1260 
1261  // The active sensor is a daughter of gnode
1262  int ndaught = gnode->GetNdaughters();
1263  if (ndaught == 0)
1264  {
1265  std::cout << PHWHERE << "OOPS: Did not find INTT sensor! Quit."
1266  << std::endl;
1267  exit(1);
1268  }
1269 
1270  std::string intt_refactive("siactive");
1271  TGeoNode *sensor_node = 0;
1272  for (int i = 0; i < ndaught; ++i)
1273  {
1274  std::string node_str = gnode->GetDaughter(i)->GetName();
1275 
1276  if (node_str.compare(0, intt_refactive.length(), intt_refactive) == 0)
1277  {
1278  sensor_node = gnode->GetDaughter(i);
1279  break;
1280  }
1281  }
1282 
1283  // unique key identifying this sensor
1284  int crossing = 0;
1285  TrkrDefs::hitsetkey node_key = InttDefs::genHitSetKey(layer, ladder_z, ladder_phi, crossing);
1286 
1287  std::pair<TrkrDefs::hitsetkey, TGeoNode *> tmp = std::make_pair(
1288  node_key, sensor_node);
1289  m_clusterNodeMap.insert(tmp);
1290 
1291  if (Verbosity() > 1)
1292  std::cout << " INTT layer " << layer << " ladder_phi " << ladder_phi
1293  << " itype " << itype << " zposneg " << zposneg
1294  << " ladder_z " << ladder_z << " name "
1295  << sensor_node->GetName() << std::endl;
1296 
1297  return;
1298 }
1299 void MakeActsGeometry::getTpcKeyFromNode(TGeoNode * /*gnode*/)
1300 {
1301 
1302 }
1304 {
1305  int counter = 0;
1306  int impr = -1; // stave number, 1-48 in TGeo
1307  int layer = -1;
1308  int stave = -1; // derived from impr
1309  int chip = -1; // 9 chips per stave
1310 
1311  std::string s = gnode->GetName();
1312  std::string delimiter = "_";
1313 
1314  size_t pos = 0;
1316 
1317  while ((pos = s.find(delimiter)) != std::string::npos)
1318  {
1319  token = s.substr(0, pos);
1320  //std::cout << token << std::endl;
1321  s.erase(0, pos + delimiter.length());
1322  if (counter == 3)
1323  impr = std::atoi(token.c_str());
1324 
1325  counter++;
1326  }
1327 
1328  // extract layer and stave info from impr
1329  // int staves_in_layer[3] = {12, 16, 20};
1330  // note - impr stave count starts from 1, not 0, but TrkrCluster counting starts from 0, so we reduce it by 1 here
1331  impr -= 1;
1332 
1333  if (impr < 12)
1334  {
1335  layer = 0;
1336  stave = impr;
1337  }
1338  else if (impr > 11 && impr < 28)
1339  {
1340  layer = 1;
1341  stave = impr - 12;
1342  }
1343  else
1344  {
1345  layer = 2;
1346  stave = impr - 28;
1347  }
1348 
1349  // Now descend node tree to find chip ID's - there are multiple chips per stave
1350  TGeoNode *module_node = gnode->GetDaughter(0);
1351  int mnd = module_node->GetNdaughters();
1352  std::string mvtx_chip("MVTXChip");
1353  for (int i = 0; i < mnd; ++i)
1354  {
1355  std::string dstr = module_node->GetDaughter(i)->GetName();
1356  if (dstr.compare(0, mvtx_chip.length(), mvtx_chip) == 0)
1357  {
1358  if (Verbosity() > 3)
1359  std::cout << "Found MVTX layer " << layer << " stave " << stave
1360  << " chip " << i << " with node name "
1361  << module_node->GetDaughter(i)->GetName() << std::endl;
1362 
1363  // Make key for this chip
1364  unsigned int strobe = 0;
1365  TrkrDefs::hitsetkey node_key = MvtxDefs::genHitSetKey(layer,
1366  stave, i, strobe);
1367 
1368  // add sensor node to map
1369  TGeoNode *sensor_node = module_node->GetDaughter(i)->GetDaughter(0);
1370  std::pair<TrkrDefs::hitsetkey, TGeoNode *> tmp = std::make_pair(
1371  node_key, sensor_node);
1372  m_clusterNodeMap.insert(tmp);
1373 
1374  if (Verbosity() > 3)
1375  std::cout << " MVTX layer " << layer << " stave " << stave
1376  << " chip " << chip << " name "
1377  << sensor_node->GetName() << std::endl;
1378  }
1379  }
1380 
1381  return;
1382 }
1383 
1384 // void MakeActsGeometry::isActive(TGeoNode *gnode, int nmax_print)
1385 // {
1386 // // Not used in analysis: diagnostic, for looking at the node tree only.
1387 // // Recursively searches gnode for silicon sensors, prints out heirarchy
1388 //
1389 // std::string node_str = gnode->GetName();
1390 //
1391 // std::string intt_refactive("siactive");
1392 // std::string mvtx_refactive("MVTXSensor");
1393 // std::string tpc_refactive("tpc_gas_measurement");
1394 // std::string micromegas_refactive("MICROMEGAS_55");
1395 //
1396 // if (node_str.compare(0, intt_refactive.length(), intt_refactive) == 0)
1397 // {
1398 // std::cout << " ******* Found INTT active volume, node is "
1399 // << gnode->GetName()
1400 // << " volume name is " << gnode->GetVolume()->GetName()
1401 // << std::endl;
1402 //
1403 // return;
1404 // }
1405 // else if (node_str.compare(0, mvtx_refactive.length(), mvtx_refactive) == 0)
1406 // {
1407 // std::cout << " ******* Found MVTX active volume, node is "
1408 // << gnode->GetName()
1409 // << " volume name is " << gnode->GetVolume()->GetName()
1410 // << std::endl;
1411 //
1412 // return;
1413 // }
1414 // else if (node_str.compare(0, tpc_refactive.length(), tpc_refactive) == 0)
1415 // {
1416 // if(nprint_tpc < nmax_print)
1417 // {
1418 // std::cout << " ******* Found TPC active volume, node is "
1419 // << gnode->GetName()
1420 // << " volume name is " << gnode->GetVolume()->GetName()
1421 // << std::endl;
1422 // }
1423 // nprint_tpc++;
1424 //
1425 // return;
1426 // }
1427 // else if (node_str.compare(0, micromegas_refactive.length(), micromegas_refactive) == 0)
1428 // {
1429 // std::cout << " ******* Found Micromegas active volume, node is "
1430 // << gnode->GetName()
1431 // << " volume name is " << gnode->GetVolume()->GetName()
1432 // << std::endl;
1433 //
1434 // return;
1435 // }
1436 // else
1437 // {
1438 // if(nprint_tpc < nmax_print)
1439 // {
1440 // std::cout << " ******* Found node "
1441 // << gnode->GetName()
1442 // << " volume name is " << gnode->GetVolume()->GetName()
1443 // << std::endl;
1444 // }
1445 // nprint_tpc++;
1446 //
1447 // return;
1448 // }
1449 //
1450 //
1451 // int ndaught = gnode->GetNdaughters();
1452 //
1453 // for (int i = 0; i < ndaught; ++i)
1454 // {
1455 // std::cout << " " << gnode->GetVolume()->GetName()
1456 // << " daughter " << i << " has name "
1457 // << gnode->GetDaughter(i)->GetVolume()->GetName() << std::endl;
1458 //
1459 // isActive(gnode->GetDaughter(i), nmax_print);
1460 // }
1461 // }
1462 
1463 
1465 {
1468  m_surfStepZ = (m_maxSurfZ - m_minSurfZ) / (double) m_nSurfZ;
1469  m_moduleStepPhi = 2.0 * M_PI / 12.0;
1470  m_modulePhiStart = -M_PI;
1472 
1473  int layer=0;
1475  for (PHG4TpcCylinderGeomContainer::ConstIterator layeriter = layerrange.first;
1476  layeriter != layerrange.second;
1477  ++layeriter)
1478  {
1479  m_layerRadius[layer] = layeriter->second->get_radius();
1480  m_layerThickness[layer] = layeriter->second->get_thickness();
1481  layer++;
1482  }
1483 
1484 }
1485 
1487 {
1488 
1489  PHNodeIterator iter(topNode);
1491  PHCompositeNode *parNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "PAR"));
1492 
1494  if (!parNode)
1495  {
1496  std::cout << "PAR Node missing, creating it" << std::endl;
1497  parNode = new PHCompositeNode("PAR");
1498  topNode->addNode(parNode);
1499  }
1500 
1501  PHNodeIterator pariter(parNode);
1503  PHCompositeNode *svtxNode = dynamic_cast<PHCompositeNode *>(pariter.findFirst("PHCompositeNode", "SVTX"));
1504 
1506  if (!svtxNode)
1507  {
1508  svtxNode = new PHCompositeNode("SVTX");
1509  parNode->addNode(svtxNode);
1510  }
1511 
1512  m_actsGeometry = findNode::getClass<ActsGeometry>(topNode, "ActsGeometry");
1513  if(!m_actsGeometry)
1514  {
1515  m_actsGeometry = new ActsGeometry();
1516  PHDataNode<ActsGeometry> *tGeoNode
1517  = new PHDataNode<ActsGeometry>(m_actsGeometry, "ActsGeometry");
1518  svtxNode->addNode(tGeoNode);
1519  }
1520 
1522 }
1523 
1524 /*
1525  * GetNodes():
1526  * Get all the all the required nodes off the node tree
1527  */
1529 {
1531  if (!m_geoManager)
1532  {
1533  std::cout << PHWHERE << " Did not find TGeoManager, quit! "
1534  << std::endl;
1536  }
1537 
1539  PHG4CylinderGeomContainer>(topNode, "CYLINDERGEOM_MVTX");
1540  if (!m_geomContainerMvtx)
1541  {
1542  std::cout << PHWHERE
1543  << " CYLINDERGEOM_MVTX node not found on node tree"
1544  << std::endl;
1546  }
1547 
1549  findNode::getClass<PHG4TpcCylinderGeomContainer>(topNode, "CYLINDERCELLGEOM_SVTX");
1550  if (!m_geomContainerTpc)
1551  {
1552  std::cout << PHWHERE
1553  << "ERROR: Can't find node CYLINDERCELLGEOM_SVTX"
1554  << std::endl;
1555  topNode->print();
1556  auto se = Fun4AllServer::instance();
1557  se->Print();
1559  }
1560 
1562  PHG4CylinderGeomContainer>(topNode, "CYLINDERGEOM_INTT");
1563  if (!m_geomContainerIntt)
1564  {
1565  std::cout << PHWHERE
1566  << " CYLINDERGEOM_INTT node not found on node tree"
1567  << std::endl;
1569  }
1570 
1571  m_geomContainerMicromegas = findNode::getClass<PHG4CylinderGeomContainer>(topNode, "CYLINDERGEOM_MICROMEGAS_FULL");
1573  {
1574  std::cout << PHWHERE
1575  << " CYLINDERGEOM_MICROMEGAS_FULL node not found on node tree"
1576  << std::endl;
1578  }
1579 
1581 }
1582