Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-03-17 11:25:03

0001 #include "SimG4Core/Notification/interface/BeginOfRun.h"
0002 #include "SimG4Core/Notification/interface/Observer.h"
0003 #include "SimG4Core/Watcher/interface/SimWatcher.h"
0004 
0005 #include "FWCore/Framework/interface/EventSetup.h"
0006 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0007 #include "DataFormats/Math/interface/angle_units.h"
0008 #include "Geometry/Records/interface/IdealGeometryRecord.h"
0009 #include "DetectorDescription/Core/interface/DDCompactView.h"
0010 #include "DetectorDescription/Core/interface/DDFilter.h"
0011 #include "DetectorDescription/Core/interface/DDFilteredView.h"
0012 #include "DetectorDescription/Core/interface/DDLogicalPart.h"
0013 #include "DetectorDescription/Core/interface/DDSplit.h"
0014 #include "DetectorDescription/Core/interface/DDValue.h"
0015 #include "DetectorDescription/DDCMS/interface/DDCompactView.h"
0016 #include "DetectorDescription/DDCMS/interface/DDFilteredView.h"
0017 
0018 #include "DD4hep/DD4hepUnits.h"
0019 #include "DD4hep/Filter.h"
0020 
0021 #include "G4LogicalVolumeStore.hh"
0022 #include "G4LogicalVolume.hh"
0023 #include "G4VSolid.hh"
0024 #include "G4Material.hh"
0025 #include "G4NavigationHistory.hh"
0026 #include "G4PhysicalVolumeStore.hh"
0027 #include "G4Region.hh"
0028 #include "G4RegionStore.hh"
0029 #include "G4Run.hh"
0030 #include "G4Track.hh"
0031 #include "G4TransportationManager.hh"
0032 #include "G4UserLimits.hh"
0033 #include "G4VisAttributes.hh"
0034 #include "G4VPhysicalVolume.hh"
0035 
0036 #include <algorithm>
0037 #include <fstream>
0038 #include <map>
0039 #include <set>
0040 #include <string>
0041 #include <vector>
0042 
0043 using angle_units::operators::convertRadToDeg;
0044 
0045 typedef std::multimap<G4LogicalVolume *, G4VPhysicalVolume *, std::less<G4LogicalVolume *> > mmlvpv;
0046 
0047 class PrintGeomInfoAction : public SimWatcher, public Observer<const BeginOfRun *> {
0048 public:
0049   PrintGeomInfoAction(edm::ParameterSet const &p);
0050   ~PrintGeomInfoAction() override = default;
0051 
0052   void registerConsumes(edm::ConsumesCollector) override;
0053   void beginRun(edm::EventSetup const &) override;
0054 
0055 private:
0056   void update(const BeginOfRun *run) override;
0057   void dumpSummary(std::ostream &out = G4cout);
0058   void dumpG4LVList(std::ostream &out = G4cout);
0059   void dumpG4LVTree(std::ostream &out = G4cout);
0060   void dumpG4Region(std::ostream &out = G4cout);
0061   void dumpMaterialList(std::ostream &out = G4cout);
0062   void dumpG4LVLeaf(G4LogicalVolume *lv, unsigned int leafDepth, unsigned int count, std::ostream &out = G4cout);
0063   int countNoTouchables();
0064   void add1touchable(G4LogicalVolume *lv, int &nTouch);
0065   void dumpHierarchyTreePVLV(std::ostream &out = G4cout);
0066   void dumpHierarchyLeafPVLV(G4LogicalVolume *lv, unsigned int leafDepth, std::ostream &out = G4cout);
0067   void dumpLV(G4LogicalVolume *lv, unsigned int leafDepth, std::ostream &out = G4cout);
0068   void dumpPV(G4VPhysicalVolume *pv, unsigned int leafDepth, std::ostream &out = G4cout);
0069   void dumpSolid(G4VSolid *sol, unsigned int leafDepth, std::ostream &out = G4cout);
0070   void dumpTouch(G4VPhysicalVolume *pv, unsigned int leafDepth, std::ostream &out = G4cout);
0071   void dumpInFile();
0072   void getTouch(G4VPhysicalVolume *pv, unsigned int leafDepth, unsigned int copym, std::vector<std::string> &touches);
0073   std::string spacesFromLeafDepth(unsigned int leafDepth);
0074   G4VPhysicalVolume *getTopPV();
0075   G4LogicalVolume *getTopLV();
0076 
0077 private:
0078   edm::ESGetToken<cms::DDCompactView, IdealGeometryRecord> dd4hepToken_;
0079   edm::ESGetToken<DDCompactView, IdealGeometryRecord> dddToken_;
0080 
0081   bool dumpSummary_, dumpLVTree_, dumpLVList_, dumpMaterial_;
0082   bool dumpLV_, dumpSolid_, dumpAtts_, dumpPV_;
0083   bool dumpRotation_, dumpReplica_, dumpTouch_;
0084   bool dumpSense_, dumpParams_, dumpRegion_, dd4hep_;
0085   std::string name_;
0086   int nchar_;
0087   std::string fileMat_, fileSolid_, fileLV_, filePV_, fileTouch_, fileRegion_;
0088   bool fileDetail_;
0089   std::vector<std::string> names_;
0090   G4VPhysicalVolume *theTopPV_;
0091   G4NavigationHistory fHistory_;
0092 };
0093 
0094 PrintGeomInfoAction::PrintGeomInfoAction(const edm::ParameterSet &p) {
0095   dumpSummary_ = p.getUntrackedParameter<bool>("DumpSummary", true);
0096   dumpLVTree_ = p.getUntrackedParameter<bool>("DumpLVTree", true);
0097   dumpLVList_ = p.getUntrackedParameter<bool>("DumpLVList", false);
0098   dumpMaterial_ = p.getUntrackedParameter<bool>("DumpMaterial", false);
0099   dumpLV_ = p.getUntrackedParameter<bool>("DumpLV", false);
0100   dumpSolid_ = p.getUntrackedParameter<bool>("DumpSolid", false);
0101   dumpAtts_ = p.getUntrackedParameter<bool>("DumpAttributes", false);
0102   dumpPV_ = p.getUntrackedParameter<bool>("DumpPV", false);
0103   dumpRotation_ = p.getUntrackedParameter<bool>("DumpRotation", false);
0104   dumpReplica_ = p.getUntrackedParameter<bool>("DumpReplica", false);
0105   dumpTouch_ = p.getUntrackedParameter<bool>("DumpTouch", false);
0106   dumpSense_ = p.getUntrackedParameter<bool>("DumpSense", false);
0107   dumpParams_ = p.getUntrackedParameter<bool>("DumpParams", false);
0108   dumpRegion_ = p.getUntrackedParameter<bool>("DumpRegion", false);
0109   dd4hep_ = p.getUntrackedParameter<bool>("DD4hep", false);
0110   name_ = p.getUntrackedParameter<std::string>("Name", "*");
0111   names_ = p.getUntrackedParameter<std::vector<std::string> >("Names");
0112   fileMat_ = p.getUntrackedParameter<std::string>("MaterialFileName", "");
0113   fileSolid_ = p.getUntrackedParameter<std::string>("SolidFileName", "");
0114   fileLV_ = p.getUntrackedParameter<std::string>("LVFileName", "");
0115   filePV_ = p.getUntrackedParameter<std::string>("PVFileName", "");
0116   fileTouch_ = p.getUntrackedParameter<std::string>("TouchFileName", "");
0117   fileRegion_ = p.getUntrackedParameter<std::string>("RegionFileName", "");
0118   fileDetail_ = p.getUntrackedParameter<bool>("FileDetail", false);
0119   nchar_ = name_.find('*');
0120   name_.assign(name_, 0, nchar_);
0121   G4cout << "PrintGeomInfoAction:: initialised for dd4hep " << dd4hep_ << " with verbosity levels:"
0122          << " Summary   " << dumpSummary_ << " LVTree   " << dumpLVTree_ << " LVList    " << dumpLVList_ << " Material "
0123          << dumpMaterial_ << G4endl << "                                                        "
0124          << " LV        " << dumpLV_ << " Solid    " << dumpSolid_ << " Attribs   " << dumpAtts_ << G4endl
0125          << "                                                        "
0126          << " PV        " << dumpPV_ << " Rotation " << dumpRotation_ << " Replica   " << dumpReplica_ << G4endl
0127          << "                                                        "
0128          << " Touchable " << dumpTouch_ << " Rgion " << dumpRegion_ << " for names (0-" << nchar_ << ") = " << name_
0129          << G4endl << "                                                        "
0130          << " Sensitive " << dumpSense_ << " Files " << fileMat_ << ":" << fileSolid_ << ":" << fileLV_ << ":"
0131          << filePV_ << ":" << fileTouch_ << " FileDetail " << fileDetail_ << " fileRegion " << fileRegion_ << G4endl
0132          << "                                                        for " << names_.size() << " names:";
0133   for (unsigned int i = 0; i < names_.size(); i++)
0134     G4cout << " " << names_[i];
0135   G4cout << G4endl;
0136 }
0137 
0138 void PrintGeomInfoAction::registerConsumes(edm::ConsumesCollector cc) {
0139   if (dd4hep_) {
0140     dd4hepToken_ = cc.esConsumes<cms::DDCompactView, IdealGeometryRecord, edm::Transition::BeginRun>();
0141     G4cout << "PrintGeomInfoAction::Initialize ESGetToken for cms::DDCompactView" << G4endl;
0142   } else {
0143     dddToken_ = cc.esConsumes<DDCompactView, IdealGeometryRecord, edm::Transition::BeginRun>();
0144     G4cout << "PrintGeomInfoAction::Initialize ESGetToken for DDCompactView" << G4endl;
0145   }
0146 }
0147 
0148 void PrintGeomInfoAction::beginRun(edm::EventSetup const &es) {
0149   if (dumpSense_) {
0150     if (dd4hep_) {
0151       const cms::DDCompactView *pDD = &es.getData(dd4hepToken_);
0152 
0153       G4cout << "PrintGeomInfoAction::Get Printout of Sensitive Volumes "
0154              << "for " << names_.size() << " Readout Units" << G4endl;
0155       for (unsigned int i = 0; i < names_.size(); i++) {
0156         std::string sd = names_[i];
0157         const cms::DDFilter filter("ReadOutName", sd);
0158         cms::DDFilteredView fv(*pDD, filter);
0159         G4cout << "PrintGeomInfoAction:: Get Filtered view for ReadOutName = " << sd << G4endl;
0160         G4cout << "Lengths are in mm, angles in degrees" << G4endl;
0161 
0162         std::string spaces = spacesFromLeafDepth(1);
0163 
0164         while (fv.firstChild()) {
0165           auto tran = fv.translation() / dd4hep::mm;
0166           std::vector<int> copy = fv.copyNos();
0167           auto lvname = fv.name();
0168           unsigned int leafDepth = copy.size();
0169           G4cout << leafDepth << spaces << "### VOLUME = " << lvname << " Copy No";
0170           for (unsigned int k = 0; k < leafDepth; ++k)
0171             G4cout << " " << copy[k];
0172           if (dumpParams_) {
0173             G4cout << " parameters";
0174             for (double val : fv.parameters()) {
0175               if (std::abs(val) < 1.0) {
0176                 G4cout << std::setprecision(5);
0177               } else
0178                 G4cout << std::setprecision(6);
0179               G4cout << " " << val;
0180             }
0181             G4cout << G4endl;
0182           } else {
0183             G4cout << " Centre at " << tran << " (r = " << tran.Rho() << ", phi = " << convertRadToDeg(tran.phi())
0184                    << ")" << G4endl;
0185           }
0186         }
0187       }
0188     } else {
0189       const DDCompactView *pDD = &es.getData(dddToken_);
0190 
0191       G4cout << "PrintGeomInfoAction::Get Printout of Sensitive Volumes "
0192              << "for " << names_.size() << " Readout Units" << G4endl;
0193       for (unsigned int i = 0; i < names_.size(); i++) {
0194         std::string attribute = "ReadOutName";
0195         std::string sd = names_[i];
0196         DDSpecificsMatchesValueFilter filter{DDValue(attribute, sd, 0)};
0197         DDFilteredView fv(*pDD, filter);
0198         G4cout << "PrintGeomInfoAction:: Get Filtered view for " << attribute << " = " << sd << G4endl;
0199         G4cout << "Lengths are in mm, angles in degrees" << G4endl;
0200         bool dodet = fv.firstChild();
0201 
0202         std::string spaces = spacesFromLeafDepth(1);
0203 
0204         while (dodet) {
0205           const DDLogicalPart &log = fv.logicalPart();
0206           std::string lvname = log.name().name();
0207           DDTranslation tran = fv.translation();
0208           std::vector<int> copy = fv.copyNumbers();
0209 
0210           unsigned int leafDepth = copy.size();
0211           G4cout << leafDepth << spaces << "### VOLUME = " << lvname << " Copy No";
0212           for (int k = leafDepth - 1; k >= 0; k--)
0213             G4cout << " " << copy[k];
0214           G4cout << " Centre at " << tran << " (r = " << tran.Rho() << ", phi = " << convertRadToDeg(tran.phi()) << ")"
0215                  << G4endl;
0216           dodet = fv.next();
0217         }
0218       }
0219     }
0220   }
0221 }
0222 
0223 void PrintGeomInfoAction::update(const BeginOfRun *run) {
0224   //Now take action
0225   theTopPV_ = getTopPV();
0226 
0227   if (dumpSummary_)
0228     dumpSummary(G4cout);
0229   if (dumpLVTree_)
0230     dumpG4LVTree(G4cout);
0231 
0232   //---------- Dump list of objects of each class with detail of parameters
0233   if (dumpMaterial_)
0234     dumpMaterialList(G4cout);
0235   if (dumpLVList_)
0236     dumpG4LVList(G4cout);
0237 
0238   //---------- Dump LV and PV information
0239   if (dumpLV_ || dumpPV_ || dumpTouch_)
0240     dumpHierarchyTreePVLV(G4cout);
0241 
0242   //---------- Dump Region information
0243   if (dumpRegion_)
0244     dumpG4Region(G4cout);
0245 
0246   dumpInFile();
0247 }
0248 
0249 void PrintGeomInfoAction::dumpSummary(std::ostream &out) {
0250   //---------- Dump number of objects of each class
0251   out << " @@@@@@@@@@@@@@@@@@ Dumping G4 geometry objects Summary " << G4endl;
0252   if (theTopPV_ == nullptr) {
0253     out << " No volume created " << G4endl;
0254     return;
0255   }
0256   out << " @@@ Geometry built inside world volume: " << theTopPV_->GetName() << G4endl;
0257   // Get number of solids (< # LV if several LV share a solid)
0258   const G4LogicalVolumeStore *lvs = G4LogicalVolumeStore::GetInstance();
0259   std::vector<G4LogicalVolume *>::const_iterator lvcite;
0260   std::set<G4VSolid *> theSolids;
0261   for (lvcite = lvs->begin(); lvcite != lvs->end(); lvcite++)
0262     theSolids.insert((*lvcite)->GetSolid());
0263   out << " Number of G4VSolid's: " << theSolids.size() << G4endl;
0264   out << " Number of G4LogicalVolume's: " << lvs->size() << G4endl;
0265   const G4PhysicalVolumeStore *pvs = G4PhysicalVolumeStore::GetInstance();
0266   out << " Number of G4VPhysicalVolume's: " << pvs->size() << G4endl;
0267   out << " Number of Touchable's: " << countNoTouchables() << G4endl;
0268   const G4MaterialTable *matTab = G4Material::GetMaterialTable();
0269   out << " Number of G4Material's: " << matTab->size() << G4endl;
0270   const G4RegionStore *regs = G4RegionStore::GetInstance();
0271   out << " Number of G4Region's: " << regs->size() << G4endl;
0272 }
0273 
0274 void PrintGeomInfoAction::dumpG4LVList(std::ostream &out) {
0275   out << " @@@@@@@@@@@@@@@@ DUMPING G4LogicalVolume's List  " << G4endl;
0276   const G4LogicalVolumeStore *lvs = G4LogicalVolumeStore::GetInstance();
0277   std::vector<G4LogicalVolume *>::const_iterator lvcite;
0278   for (lvcite = lvs->begin(); lvcite != lvs->end(); lvcite++)
0279     out << "LV:" << (*lvcite)->GetName() << "\tMaterial: " << (*lvcite)->GetMaterial()->GetName() << G4endl;
0280 }
0281 
0282 void PrintGeomInfoAction::dumpG4LVTree(std::ostream &out) {
0283   out << " @@@@@@@@@@@@@@@@ DUMPING G4LogicalVolume's Tree  " << G4endl;
0284   G4LogicalVolume *lv = getTopLV();
0285   dumpG4LVLeaf(lv, 0, 1, out);
0286 }
0287 
0288 void PrintGeomInfoAction::dumpG4Region(std::ostream &out) {
0289   out << " @@@@@@@@@@@@@@@@ DUMPING G4Region Tree  " << G4endl;
0290   const G4RegionStore *regs = G4RegionStore::GetInstance();
0291   std::vector<G4Region *>::const_iterator regite;
0292   for (regite = regs->begin(); regite != regs->end(); regite++)
0293     out << "Region: " << (*regite)->GetName() << " with " << (*regite)->GetNumberOfMaterials() << " materials and "
0294         << (*regite)->GetNumberOfRootVolumes() << " root volumes" << G4endl;
0295 }
0296 
0297 void PrintGeomInfoAction::dumpMaterialList(std::ostream &out) {
0298   out << " @@@@@@@@@@@@@@@@ DUMPING G4Material List ";
0299   const G4MaterialTable *matTab = G4Material::GetMaterialTable();
0300   out << " with " << matTab->size() << " materials " << G4endl;
0301   std::vector<G4Material *>::const_iterator matite;
0302   for (matite = matTab->begin(); matite != matTab->end(); matite++)
0303     out << "Material: " << (*matite) << G4endl;
0304 }
0305 
0306 void PrintGeomInfoAction::dumpG4LVLeaf(G4LogicalVolume *lv,
0307                                        unsigned int leafDepth,
0308                                        unsigned int count,
0309                                        std::ostream &out) {
0310   for (unsigned int ii = 0; ii < leafDepth; ii++)
0311     out << "  ";
0312   out << " LV:(" << leafDepth << ") " << lv->GetName() << " (" << count << ")" << G4endl;
0313   //--- If a volume is placed n types as daughter of this LV, it should only be counted once
0314   std::map<G4LogicalVolume *, unsigned int> lvCount;
0315   std::map<G4LogicalVolume *, unsigned int>::const_iterator cite;
0316   int siz = lv->GetNoDaughters();
0317   for (int ii = 0; ii < siz; ii++) {
0318     cite = lvCount.find(lv->GetDaughter(ii)->GetLogicalVolume());
0319     if (cite != lvCount.end())
0320       lvCount[cite->first] = (cite->second) + 1;
0321     else
0322       lvCount.insert(std::pair<G4LogicalVolume *, unsigned int>(lv->GetDaughter(ii)->GetLogicalVolume(), 1));
0323   }
0324   for (cite = lvCount.begin(); cite != lvCount.end(); cite++)
0325     dumpG4LVLeaf((cite->first), leafDepth + 1, (cite->second), out);
0326 }
0327 
0328 int PrintGeomInfoAction::countNoTouchables() {
0329   int nTouch = 0;
0330   G4LogicalVolume *lv = getTopLV();
0331   add1touchable(lv, nTouch);
0332   return nTouch;
0333 }
0334 
0335 void PrintGeomInfoAction::add1touchable(G4LogicalVolume *lv, int &nTouch) {
0336   int siz = lv->GetNoDaughters();
0337   for (int ii = 0; ii < siz; ii++)
0338     add1touchable(lv->GetDaughter(ii)->GetLogicalVolume(), ++nTouch);
0339 }
0340 
0341 void PrintGeomInfoAction::dumpHierarchyTreePVLV(std::ostream &out) {
0342   //dumps in the following order:
0343   //    1) a LV with details
0344   //    2) list of PVs daughters of this LV with details
0345   //    3) list of LVs daughters of this LV and for each go to 1)
0346 
0347   //----- Get top PV
0348   G4LogicalVolume *topLV = getTopLV();
0349 
0350   //----- Dump this leaf (it will recursively dump all the tree)
0351   dumpHierarchyLeafPVLV(topLV, 0, out);
0352   dumpPV(theTopPV_, 0, out);
0353 
0354   //----- Dump the touchables (it will recursively dump all the tree)
0355   if (dumpTouch_)
0356     dumpTouch(theTopPV_, 0, out);
0357 }
0358 
0359 void PrintGeomInfoAction::dumpHierarchyLeafPVLV(G4LogicalVolume *lv, unsigned int leafDepth, std::ostream &out) {
0360   //----- Dump this LV
0361   dumpLV(lv, leafDepth, out);
0362 
0363   //----- Get LV daughters from list of PV daughters
0364   mmlvpv lvpvDaughters;
0365   std::set<G4LogicalVolume *> lvDaughters;
0366   int NoDaughters = lv->GetNoDaughters();
0367   while ((NoDaughters--) > 0) {
0368     G4VPhysicalVolume *pvD = lv->GetDaughter(NoDaughters);
0369     lvpvDaughters.insert(mmlvpv::value_type(pvD->GetLogicalVolume(), pvD));
0370     lvDaughters.insert(pvD->GetLogicalVolume());
0371   }
0372 
0373   std::set<G4LogicalVolume *>::const_iterator scite;
0374   mmlvpv::const_iterator mmcite;
0375 
0376   //----- Dump daughters PV and LV
0377   for (scite = lvDaughters.begin(); scite != lvDaughters.end(); scite++) {
0378     std::pair<mmlvpv::iterator, mmlvpv::iterator> mmER = lvpvDaughters.equal_range(*scite);
0379     //----- Dump daughters PV of this LV
0380     for (mmcite = mmER.first; mmcite != mmER.second; mmcite++)
0381       dumpPV((*mmcite).second, leafDepth + 1, out);
0382     //----- Dump daughters LV
0383     dumpHierarchyLeafPVLV(*scite, leafDepth + 1, out);
0384   }
0385 }
0386 
0387 void PrintGeomInfoAction::dumpLV(G4LogicalVolume *lv, unsigned int leafDepth, std::ostream &out) {
0388   std::string spaces = spacesFromLeafDepth(leafDepth);
0389 
0390   //----- dump name
0391   if (dumpLV_) {
0392     out << leafDepth << spaces << "$$$ VOLUME = " << lv->GetName() << "  Solid: " << lv->GetSolid()->GetName()
0393         << "  MATERIAL: " << lv->GetMaterial()->GetName() << G4endl;
0394     if (dumpSolid_)
0395       dumpSolid(lv->GetSolid(), leafDepth, out);  //----- dump solid
0396 
0397     //----- dump LV info
0398     //--- material
0399     if (dumpAtts_) {
0400       //--- Visualisation attributes
0401       const G4VisAttributes *fVA = lv->GetVisAttributes();
0402       if (fVA != nullptr) {
0403         out << spaces << "  VISUALISATION ATTRIBUTES: " << G4endl;
0404         out << spaces << "    IsVisible " << fVA->IsVisible() << G4endl;
0405         out << spaces << "    IsDaughtersInvisible " << fVA->IsDaughtersInvisible() << G4endl;
0406         out << spaces << "    Colour " << fVA->GetColour() << G4endl;
0407         out << spaces << "    LineStyle " << fVA->GetLineStyle() << G4endl;
0408         out << spaces << "    LineWidth " << fVA->GetLineWidth() << G4endl;
0409         out << spaces << "    IsForceDrawingStyle " << fVA->IsForceDrawingStyle() << G4endl;
0410         out << spaces << "    ForcedDrawingStyle " << fVA->GetForcedDrawingStyle() << G4endl;
0411       }
0412 
0413       //--- User Limits
0414       G4UserLimits *fUL = lv->GetUserLimits();
0415       G4Track dummy;
0416       if (fUL != nullptr) {
0417         out << spaces << "    MaxAllowedStep " << fUL->GetMaxAllowedStep(dummy) << G4endl;
0418         out << spaces << "    UserMaxTrackLength " << fUL->GetUserMaxTrackLength(dummy) << G4endl;
0419         out << spaces << "    UserMaxTime " << fUL->GetUserMaxTime(dummy) << G4endl;
0420         out << spaces << "    UserMinEkine " << fUL->GetUserMinEkine(dummy) << G4endl;
0421         out << spaces << "    UserMinRange " << fUL->GetUserMinRange(dummy) << G4endl;
0422       }
0423 
0424       //--- other LV info
0425       if (lv->GetSensitiveDetector())
0426         out << spaces << "  IS SENSITIVE DETECTOR " << G4endl;
0427       if (lv->GetFieldManager())
0428         out << spaces << "  FIELD ON " << G4endl;
0429 
0430       // Pointer (possibly NULL) to optimisation info objects.
0431       out << spaces << "        Quality for optimisation, average number of voxels to be spent per content "
0432           << lv->GetSmartless() << G4endl;
0433 
0434       // Pointer (possibly NULL) to G4FastSimulationManager object.
0435       if (lv->GetFastSimulationManager())
0436         out << spaces << "     Logical Volume is an envelope for a FastSimulationManager " << G4endl;
0437       out << spaces << "     Weight used in the event biasing technique = " << lv->GetBiasWeight() << G4endl;
0438     }
0439   }
0440 }
0441 
0442 void PrintGeomInfoAction::dumpPV(G4VPhysicalVolume *pv, unsigned int leafDepth, std::ostream &out) {
0443   std::string spaces = spacesFromLeafDepth(leafDepth);
0444 
0445   //----- PV info
0446   if (dumpPV_) {
0447     std::string mother = "World";
0448     if (pv->GetMotherLogical())
0449       mother = pv->GetMotherLogical()->GetName();
0450     out << leafDepth << spaces << "### VOLUME = " << pv->GetName() << " Copy No " << pv->GetCopyNo() << " in " << mother
0451         << " at " << pv->GetTranslation();
0452   }
0453   if (!pv->IsReplicated()) {
0454     if (dumpPV_) {
0455       if (pv->GetRotation() == nullptr)
0456         out << " with no rotation" << G4endl;
0457       else if (!dumpRotation_)
0458         out << " with rotation" << G4endl;  //just rotation name
0459       else
0460         out << " with rotation " << *(pv->GetRotation()) << G4endl;
0461     }
0462   } else {
0463     if (dumpReplica_) {
0464       out << spaces << "    It is replica: " << G4endl;
0465       EAxis axis;
0466       int nReplicas;
0467       double width;
0468       double offset;
0469       bool consuming;
0470       pv->GetReplicationData(axis, nReplicas, width, offset, consuming);
0471       out << spaces << "     axis " << axis << G4endl << spaces << "     nReplicas " << nReplicas << G4endl;
0472       if (pv->GetParameterisation() != nullptr)
0473         out << spaces << "    It is parameterisation " << G4endl;
0474       else
0475         out << spaces << "     width " << width << G4endl << spaces << "     offset " << offset << G4endl << spaces
0476             << "     consuming" << consuming << G4endl;
0477       if (pv->GetParameterisation() != nullptr)
0478         out << spaces << "    It is parameterisation " << G4endl;
0479     }
0480   }
0481 }
0482 
0483 void PrintGeomInfoAction::dumpSolid(G4VSolid *sol, unsigned int leafDepth, std::ostream &out) {
0484   std::string spaces = spacesFromLeafDepth(leafDepth);
0485   out << spaces << *(sol) << G4endl;
0486 }
0487 
0488 void PrintGeomInfoAction::dumpTouch(G4VPhysicalVolume *pv, unsigned int leafDepth, std::ostream &out) {
0489   std::string spaces = spacesFromLeafDepth(leafDepth);
0490   if (leafDepth == 0)
0491     fHistory_.SetFirstEntry(pv);
0492   else
0493     fHistory_.NewLevel(pv, kNormal, pv->GetCopyNo());
0494 
0495   G4ThreeVector globalpoint = fHistory_.GetTopTransform().Inverse().TransformPoint(G4ThreeVector(0, 0, 0));
0496   G4LogicalVolume *lv = pv->GetLogicalVolume();
0497 
0498   std::string mother = "World";
0499   if (pv->GetMotherLogical())
0500     mother = pv->GetMotherLogical()->GetName();
0501   std::string lvname = lv->GetName();
0502   lvname.assign(lvname, 0, nchar_);
0503   if (lvname == name_)
0504     out << leafDepth << spaces << "### VOLUME = " << lv->GetName() << " Copy No " << pv->GetCopyNo() << " in " << mother
0505         << " global position of centre " << globalpoint << " (r = " << globalpoint.perp()
0506         << ", phi = " << convertRadToDeg(globalpoint.phi()) << ")" << G4endl;
0507 
0508   int NoDaughters = lv->GetNoDaughters();
0509   while ((NoDaughters--) > 0) {
0510     G4VPhysicalVolume *pvD = lv->GetDaughter(NoDaughters);
0511     if (!pvD->IsReplicated())
0512       dumpTouch(pvD, leafDepth + 1, out);
0513   }
0514 
0515   if (leafDepth > 0)
0516     fHistory_.BackLevel();
0517 }
0518 
0519 void PrintGeomInfoAction::dumpInFile() {
0520   //---------- Dump number objects of each class in a file
0521   if (theTopPV_ != nullptr) {
0522     if (!fileMat_.empty()) {
0523       const G4MaterialTable *matTab = G4Material::GetMaterialTable();
0524       std::ofstream fout(fileMat_.c_str());
0525       for (std::vector<G4Material *>::const_iterator matite = matTab->begin(); matite != matTab->end(); matite++) {
0526         if (!fileDetail_)
0527           fout << (*matite)->GetName() << G4endl;
0528         else
0529           fout << (*matite)->GetName() << " " << (*matite)->GetRadlen() << " " << (*matite)->GetNuclearInterLength()
0530                << G4endl;
0531       }
0532       fout.close();
0533     }
0534     const G4LogicalVolumeStore *lvs = G4LogicalVolumeStore::GetInstance();
0535     if (!fileSolid_.empty()) {
0536       std::ofstream fout(fileSolid_.c_str());
0537       for (std::vector<G4LogicalVolume *>::const_iterator lvcite = lvs->begin(); lvcite != lvs->end(); lvcite++)
0538         if (!fileDetail_)
0539           fout << (*lvcite)->GetSolid()->GetName() << G4endl;
0540         else
0541           fout << (*lvcite)->GetSolid()->GetName() << "  " << (*lvcite)->GetSolid()->GetCubicVolume() << G4endl;
0542       fout.close();
0543     }
0544     if (!fileLV_.empty()) {
0545       std::ofstream fout(fileLV_.c_str());
0546       for (std::vector<G4LogicalVolume *>::const_iterator lvcite = lvs->begin(); lvcite != lvs->end(); lvcite++)
0547         if (!fileDetail_)
0548           fout << (*lvcite)->GetName() << G4endl;
0549         else
0550           fout << (*lvcite)->GetName() << "  " << (*lvcite)->GetMass(false, false) << G4endl;
0551       fout.close();
0552     }
0553     if (!filePV_.empty()) {
0554       const G4PhysicalVolumeStore *pvs = G4PhysicalVolumeStore::GetInstance();
0555       std::ofstream fout(filePV_.c_str());
0556       for (std::vector<G4VPhysicalVolume *>::const_iterator pvcite = pvs->begin(); pvcite != pvs->end(); pvcite++) {
0557         if (fileDetail_) {
0558           if (dd4hep_)
0559             fout << (*pvcite)->GetName() << " " << (*pvcite)->GetTranslation().x() << " "
0560                  << (*pvcite)->GetTranslation().y() << " " << (*pvcite)->GetTranslation().z() << G4endl;
0561           else
0562             fout << (*pvcite)->GetName() << " " << (*pvcite)->GetCopyNo() << " " << (*pvcite)->GetTranslation().x()
0563                  << " " << (*pvcite)->GetTranslation().y() << " " << (*pvcite)->GetTranslation().z() << G4endl;
0564         } else {
0565           if (dd4hep_)
0566             fout << (*pvcite)->GetName() << G4endl;
0567           else
0568             fout << (*pvcite)->GetName() << " " << (*pvcite)->GetCopyNo() << G4endl;
0569         }
0570       }
0571       fout.close();
0572     }
0573     if (!fileTouch_.empty()) {
0574       std::ofstream fout(fileTouch_.c_str());
0575       std::vector<std::string> touches;
0576       getTouch(theTopPV_, 0, 1, touches);
0577       std::sort(touches.begin(), touches.end());
0578       for (const auto &touch : touches)
0579         fout << touch << G4endl;
0580       fout.close();
0581     }
0582     if (!fileRegion_.empty()) {
0583       const G4RegionStore *regs = G4RegionStore::GetInstance();
0584       std::ofstream fout(fileRegion_.c_str());
0585       for (std::vector<G4Region *>::const_iterator regite = regs->begin(); regite != regs->end(); regite++) {
0586         if (!fileDetail_)
0587           fout << (*regite)->GetName() << G4endl;
0588         else
0589           fout << (*regite)->GetName() << " " << (*regite)->GetNumberOfMaterials() << " "
0590                << (*regite)->GetNumberOfRootVolumes() << G4endl;
0591       }
0592       fout.close();
0593     }
0594   }
0595 }
0596 
0597 void PrintGeomInfoAction::getTouch(G4VPhysicalVolume *pv,
0598                                    unsigned int leafDepth,
0599                                    unsigned int copym,
0600                                    std::vector<std::string> &touches) {
0601   if (leafDepth == 0)
0602     fHistory_.SetFirstEntry(pv);
0603   else
0604     fHistory_.NewLevel(pv, kNormal, pv->GetCopyNo());
0605 
0606   std::string mother = "World";
0607   if (pv->GetMotherLogical())
0608     mother = static_cast<std::string>(dd4hep::dd::noNamespace(pv->GetMotherLogical()->GetName()));
0609 
0610   G4LogicalVolume *lv = pv->GetLogicalVolume();
0611   std::string lvname = static_cast<std::string>(dd4hep::dd::noNamespace(lv->GetName()));
0612   unsigned int copy = static_cast<unsigned int>(pv->GetCopyNo());
0613 
0614   std::string name = lvname + ":" + std::to_string(copy) + "_" + mother + ":" + std::to_string(copym);
0615   touches.emplace_back(name);
0616 
0617   int NoDaughters = lv->GetNoDaughters();
0618   while ((NoDaughters--) > 0) {
0619     G4VPhysicalVolume *pvD = lv->GetDaughter(NoDaughters);
0620     if (!pvD->IsReplicated())
0621       getTouch(pvD, leafDepth + 1, copy, touches);
0622   }
0623 
0624   if (leafDepth > 0)
0625     fHistory_.BackLevel();
0626 }
0627 
0628 std::string PrintGeomInfoAction::spacesFromLeafDepth(unsigned int leafDepth) {
0629   std::string spaces;
0630   unsigned int ii;
0631   for (ii = 0; ii < leafDepth; ii++) {
0632     spaces += "  ";
0633   }
0634   return spaces;
0635 }
0636 
0637 G4VPhysicalVolume *PrintGeomInfoAction::getTopPV() {
0638   return G4TransportationManager::GetTransportationManager()->GetNavigatorForTracking()->GetWorldVolume();
0639 }
0640 
0641 G4LogicalVolume *PrintGeomInfoAction::getTopLV() { return theTopPV_->GetLogicalVolume(); }
0642 
0643 #include "SimG4Core/Watcher/interface/SimWatcherFactory.h"
0644 #include "FWCore/PluginManager/interface/ModuleDef.h"
0645 
0646 DEFINE_SIMWATCHER(PrintGeomInfoAction);