Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:16:57

0001 //==========================================================================
0002 //  AIDA Detector description implementation 
0003 //--------------------------------------------------------------------------
0004 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
0005 // All rights reserved.
0006 //
0007 // For the licensing terms see $DD4hepINSTALL/LICENSE.
0008 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
0009 //
0010 // Author     : M.Frank
0011 //
0012 //==========================================================================
0013 
0014 // Framework include files
0015 #include <DD4hep/Printout.h>
0016 #include <DD4hep/DD4hepRootPersistency.h>
0017 #include <DD4hep/detail/ObjectsInterna.h>
0018 #include <DD4hep/detail/SegmentationsInterna.h>
0019 
0020 // ROOT include files
0021 #include <TFile.h>
0022 #include <TTimeStamp.h>
0023 #include <memory>
0024 
0025 ClassImp(DD4hepRootPersistency)
0026 
0027 using namespace dd4hep;
0028 
0029 namespace {
0030   /// Ensure nominal alignments are loaded before saving
0031   void load_nominal_alignments(DetElement de)    {
0032     de.nominal();
0033     de.survey();
0034     for(const auto& c : de.children())
0035       load_nominal_alignments(c.second);
0036   }
0037 }
0038 
0039 /// Default constructor
0040 DD4hepRootPersistency::DD4hepRootPersistency() : TNamed() {
0041 }
0042 
0043 /// Default destructor
0044 DD4hepRootPersistency::~DD4hepRootPersistency() {
0045 }
0046 
0047 int DD4hepRootPersistency::save(Detector& description, const char* fname, const char* instance)   {
0048   TFile* f = TFile::Open(fname,"RECREATE");
0049   if ( f && !f->IsZombie()) {
0050     try  {
0051       TTimeStamp start;
0052       DetectorData::patchRootStreamer(TGeoVolume::Class());
0053       DetectorData::patchRootStreamer(TGeoNode::Class());
0054       load_nominal_alignments(description.world());
0055       DD4hepRootPersistency* persist = new DD4hepRootPersistency();
0056       persist->m_data = new dd4hep::DetectorData();
0057       persist->m_data->adoptData(dynamic_cast<DetectorData&>(description),false);
0058       for( const auto& sens : persist->m_data->m_sensitive )  {
0059         dd4hep::SensitiveDetector sd = sens.second;
0060         dd4hep::Readout ro = sd.readout();
0061         if ( ro.isValid() && ro.segmentation().isValid() )  {
0062           persist->m_segments[ro].first  = ro.idSpec();
0063           persist->m_segments[ro].second = ro.segmentation().segmentation();
0064         }
0065       }
0066       if ( persist->volumeManager().isValid() )   {
0067         for( const auto& mgr : persist->m_data->m_volManager->managers )  {
0068           for( const auto& vol : mgr.second->volumes )  {
0069             persist->nominals[vol.second->element] = vol.second->element.nominal();
0070           }
0071         }
0072         printout(ALWAYS,"DD4hepRootPersistency","+++ Saving %ld nominals....",persist->nominals.size());
0073       }
0074       else  {
0075         printout(ALWAYS,
0076                  "DD4hepRootPersistency","+++ No valid Volume manager. No nominals saved.",
0077                  persist->nominals.size());
0078       }
0079     
0080       /// Now we write the object
0081       int nBytes = persist->Write(instance);
0082       f->Close();
0083       TTimeStamp stop;
0084       printout(ALWAYS,"DD4hepRootPersistency",
0085                "+++ Wrote %d Bytes of geometry data '%s' to '%s'  [%8.3f seconds].",
0086                nBytes, instance, fname, stop.AsDouble()-start.AsDouble());
0087       if ( nBytes > 0 )  {
0088         printout(ALWAYS,"DD4hepRootPersistency",
0089                  "+++ Successfully saved geometry data to file.");
0090       }
0091       delete f;
0092       delete persist;
0093       DetectorData::unpatchRootStreamer(TGeoVolume::Class());
0094       DetectorData::unpatchRootStreamer(TGeoNode::Class());
0095       return nBytes;
0096     }
0097     catch (const std::exception& e) {
0098       DetectorData::unpatchRootStreamer(TGeoVolume::Class());
0099       DetectorData::unpatchRootStreamer(TGeoNode::Class());
0100       except("DD4hepRootPersistency","Exception %s while saving file %s",e.what(), fname);
0101     }
0102     catch (...) {
0103       DetectorData::unpatchRootStreamer(TGeoVolume::Class());
0104       DetectorData::unpatchRootStreamer(TGeoNode::Class());
0105       except("DD4hepRootPersistency","UNKNOWN exception while saving file %s", fname);
0106     }
0107     return 0;
0108   }
0109   printout(ERROR,"DD4hepRootPersistency","+++ Cannot open file '%s'.",fname);
0110   return 0;
0111 }
0112 
0113 int DD4hepRootPersistency::load(Detector& description, const char* fname, const char* instance)  {
0114   DetectorData::patchRootStreamer(TGeoVolume::Class());
0115   DetectorData::patchRootStreamer(TGeoNode::Class());
0116   TFile* f = TFile::Open(fname);
0117   if ( f && !f->IsZombie()) {
0118     try  {
0119       TTimeStamp start;
0120       std::unique_ptr<DD4hepRootPersistency> persist((DD4hepRootPersistency*)f->Get(instance));
0121       if ( persist.get() )   {
0122         DetectorData* source = persist->m_data;
0123 #if 0
0124         const auto& iddesc = persist->idSpecifications();
0125         for( const auto& idd : iddesc )  {
0126           IDDescriptor id = idd.second;
0127           id.rebuild(id->description);
0128         }
0129         printout(ALWAYS,"DD4hepRootPersistency",
0130                  "+++ Fixed %ld IDDescriptor objects.",iddesc.size());
0131 #endif
0132         for( const auto& sg : persist->m_segments )  {
0133           Readout ro = sg.first;
0134           IDDescriptor id = sg.second.first;
0135           DDSegmentation::Segmentation* seg = sg.second.second;
0136           ro.setSegmentation(Segmentation(seg->type(),seg->name(),id.decoder()));
0137           delete seg;
0138         }
0139         printout(ALWAYS,"DD4hepRootPersistency",
0140                  "+++ Fixed %ld segmentation objects.",persist->m_segments.size());
0141         persist->m_segments.clear();
0142         if ( persist->volumeManager().isValid() )   {
0143           const auto& sdets = persist->volumeManager()->subdetectors;
0144           size_t num[3] = {0,0,0};
0145           for( const auto& vm : sdets )  {
0146             VolumeManager::Object* obj = vm.second.ptr();
0147             obj->system = obj->id.field("system");
0148             if ( 0 != obj->system )   {
0149               printout(ALWAYS,"DD4hepRootPersistency",
0150                        "+++ Fixed VolumeManager.system for %-24s  %6ld volumes %4ld sdets %4ld mgrs.",
0151                        obj->detector.path().c_str(), obj->volumes.size(),
0152                        obj->subdetectors.size(), obj->managers.size());
0153               num[0] += obj->volumes.size();
0154               num[1] += obj->subdetectors.size();
0155               num[2] += obj->managers.size();
0156               continue;
0157             }
0158             printout(ALWAYS,"DD4hepRootPersistency",
0159                      "+++ FAILED to fix VolumeManager.system for '%s: %s'.",
0160                      obj->detector.path().c_str(), "[No IDDescriptor field 'system']");
0161           }
0162           printout(ALWAYS,"DD4hepRootPersistency",
0163                    "+++ Fixed VolumeManager TOTALS     %-24s  %6ld volumes %4ld sdets %4ld mgrs.","",num[0],num[1],num[2]);
0164           printout(ALWAYS,"DD4hepRootPersistency","+++ loaded %ld nominals....",persist->nominals.size());
0165         }
0166         else   {
0167           printout(ALWAYS,"DD4hepRootPersistency","+++ Volume manager NOT restored. [Was it ever up when saved?]");
0168         }
0169         DetectorData* tar_data = dynamic_cast<DetectorData*>(&description);
0170         DetectorData* src_data = dynamic_cast<DetectorData*>(source);
0171         if( tar_data != nullptr && src_data != nullptr )  {
0172           tar_data->adoptData(*src_data,false);
0173           TTimeStamp stop;
0174           printout(ALWAYS,"DD4hepRootPersistency",
0175                    "+++ Successfully loaded detector description from file:%s  [%8.3f seconds]",
0176                    fname, stop.AsDouble()-start.AsDouble());
0177           DetectorData::unpatchRootStreamer(TGeoVolume::Class());
0178           DetectorData::unpatchRootStreamer(TGeoNode::Class());
0179           return 1;
0180         }
0181         DetectorData::unpatchRootStreamer(TGeoVolume::Class());
0182         DetectorData::unpatchRootStreamer(TGeoNode::Class());
0183         return 0;
0184       }
0185       printout(ERROR,"DD4hepRootPersistency",
0186                "+++ Cannot Cannot load instance '%s' from file '%s'.",
0187                instance, fname);
0188       f->ls();
0189       delete f;
0190     }
0191     catch (const std::exception& e) {
0192       DetectorData::unpatchRootStreamer(TGeoVolume::Class());
0193       DetectorData::unpatchRootStreamer(TGeoNode::Class());
0194       except("DD4hepRootPersistency","Exception %s while loading file %s",e.what(), fname);
0195     }
0196     catch (...) {
0197       DetectorData::unpatchRootStreamer(TGeoVolume::Class());
0198       DetectorData::unpatchRootStreamer(TGeoNode::Class());
0199       except("DD4hepRootPersistency","UNKNOWN exception while loading %s", fname);
0200     }
0201     return 0;
0202   }
0203   DetectorData::unpatchRootStreamer(TGeoVolume::Class());
0204   DetectorData::unpatchRootStreamer(TGeoNode::Class());
0205   printout(ERROR,"DD4hepRootPersistency","+++ Cannot open file '%s'.",fname);
0206   return 0;
0207 }
0208 
0209 #include <DD4hep/detail/DetectorInterna.h>
0210 #include <DD4hep/detail/ConditionsInterna.h>
0211 #include <DD4hep/detail/AlignmentsInterna.h>
0212 
0213 namespace {
0214 
0215   class PersistencyChecks  {
0216   public:
0217     size_t errors = 0;
0218 
0219     /// Default constructor
0220     PersistencyChecks() = default;
0221 
0222     size_t checkConstant(const std::pair<std::string,Constant>& obj)  {
0223       if ( obj.first.empty() || obj.second->name.empty() )  {
0224         printout(ERROR,"chkConstant","+++ Invalid constant: key error %s <> %s [%s]",
0225                  obj.first.c_str(), obj.second->GetName(), obj.second->GetTitle());
0226         ++errors;
0227         return 0;
0228       }
0229       if ( obj.first != obj.second->GetName() )  {
0230         printout(ERROR,"chkConstant","+++ Invalid constant: key error %s <> %s [%s]",
0231                  obj.first.c_str(), obj.second->GetName(), obj.second->GetTitle());
0232         ++errors;
0233         return 0;
0234       }
0235       return 1;
0236     }
0237     
0238     size_t checkProperty(const std::pair<std::string, std::map<std::string,std::string> >& obj)  {
0239       if ( obj.first.empty() || obj.second.empty() )  {
0240         printout(ERROR,"chkProperty","+++ Empty property set: %s",obj.first.c_str());
0241         ++errors;
0242         return 0;
0243       }
0244       return 1;
0245     }
0246     
0247     size_t printDetElement(DetElement d)  {
0248       const DetElement::Children& children = d.children();
0249       size_t count = 1;
0250       printout(INFO,"chkDetector","+++ %-40s Level:%3d Key:%08X VolID:%016llX",
0251                d.name(), d.level(), d.key(), d.volumeID());
0252       Alignment ideal = d.nominal();
0253       if ( ideal.isValid() )  {
0254         const Delta& delta = ideal.delta();
0255         printout(INFO,"chkDetector","+++     Ideal: %s  Delta:%s--%s--%s",
0256                  yes_no(ideal.isValid()),
0257                  delta.hasTranslation() ? "Translation" : "         ",
0258                  delta.hasRotation()    ? "Rotation"    : "        ",
0259                  delta.hasPivot()       ? "Pivot"       : "    "
0260                  );
0261         //ideal.worldTransformation().Print();
0262       }
0263       else  {
0264         printout(INFO,"chkDetector","+++     Ideal: %s",yes_no(ideal.isValid()));
0265       }
0266       for( const auto& c : children )
0267         count += printDetElement(c.second);
0268       return count;
0269     }
0270 
0271     size_t checkDetector(DetElement d)   {
0272       printout(INFO,"chkDetector","+++ Checking Sub-Detector: %-40s Key:%08X VolID:%016llX",
0273                d.name(), d.key(), d.volumeID());
0274       return printDetElement(d);
0275     }
0276 
0277 
0278     size_t checkSensitive(SensitiveDetector d)   {
0279       printout(INFO,"chkDetector","+++ Checking SensitiveDetector: %-30s %-16s CombineHits:%s ecut:%g Collection:%s",
0280                d.name(), ("["+d.type()+"]").c_str(),
0281                yes_no(d.combineHits()), d.energyCutoff(), d.hitsCollection().c_str());
0282       Readout ro = d.readout();
0283       if ( !ro.isValid() )  {
0284         printout(ERROR,"chkDetector",
0285                  "+++ FAILED   SensitiveDetector:%s No Readout Stricture attached.",
0286                  ro.name());
0287         ++errors;
0288         return 0;
0289       }
0290       if ( ro.isValid() )  {
0291         if ( !checkReadout(ro) )  {
0292           return 0;
0293         }
0294       }
0295       return 1;
0296     }
0297 
0298     size_t checkReadout(Readout ro)  {
0299       size_t ret = 1;
0300       printout(INFO,"chkReadOut","+++ Checking Readout: %s Collection No:%ld IDspec:%s",
0301                ro.name(), ro.numCollections(), yes_no(ro.idSpec().isValid()));
0302       IDDescriptor id = ro.idSpec();
0303       if ( id.isValid() )  {
0304         if ( !checkIDDescriptor(id) ) ret = 0;
0305       }
0306       else  {
0307         printout(ERROR,"chkReadOut",
0308                  "+++ FAILED   Segmentation: %s Found readout without ID descriptor!",
0309                  ro.name());
0310         ++errors;
0311         ret = 0;
0312       }
0313       Segmentation sg = ro.segmentation();
0314       if ( sg.isValid() )  {
0315         DDSegmentation::Segmentation* seg = sg.segmentation();
0316         if ( !checkSegmentation(sg) )  {
0317           ret = 0;
0318         }
0319         if ( id.isValid() && seg && id.decoder() != sg.decoder() )  {
0320           printout(ERROR,"chkReadOut","+++ FAILED   Decoder ERROR:%p != %p",
0321                    (void*)seg->decoder(), (void*)id.decoder());
0322           ++errors;
0323           ret = 0;
0324         }        
0325       }
0326       return ret;
0327     }
0328 
0329     size_t checkSegmentation(Segmentation sg)  {
0330       DDSegmentation::Segmentation* seg = sg.segmentation();
0331       if ( seg )  {
0332         size_t ret = 1;
0333         printout(INFO,"chkSegment","+++ Checking Segmentation: %-24s [%s] DDSegmentation:%p  Decoder:%p",
0334                  sg.name(), seg->type().c_str(),(void*)seg, seg->decoder());
0335         const auto& pars = seg->parameters();
0336         for ( const auto& par : pars )   {
0337           printout(INFO,"chkSegment","+++             Param:%-24s  -> %-16s  [%s] opt:%s",
0338                    par->name().c_str(), par->value().c_str(), par->type().c_str(),
0339                    yes_no(par->isOptional()));
0340             
0341         }
0342         if ( pars.empty() )   {
0343           printout(ERROR,"chkSegment",
0344                    "+++ FAILED   Segmentation: %s Found readout with invalid [EMPTY] ID descriptor!",
0345                    sg.name());
0346           ++errors;
0347           ret = 0;
0348         }
0349         if ( !seg->decoder() )   {
0350           printout(ERROR,"chkSegment","+++ FAILED   Segmentation: %s  NO Decoder!!!",
0351                    sg.name());
0352           ++errors;
0353           ret = 0;
0354         }
0355         return ret;
0356       }
0357       printout(ERROR,"chkSegment","+++ FAILED   Segmentation: %s  NO DDSegmentation",
0358                sg.name());
0359       ++errors;
0360       return 0;
0361     }
0362 
0363     size_t checkIDDescriptor(IDDescriptor id)   {
0364       const IDDescriptor::FieldMap& fields = id.fields();
0365       printout(INFO,"chkIDDescript","+++ Checking IDDesc:  %s decoder:%p",
0366                id->GetName(), (void*)id.decoder());
0367       printout(INFO,"chkIDDescript","+++             Specs:%s",id.fieldDescription().c_str());
0368       for( const auto& fld : fields )
0369         printout(INFO,"chkIDDescript","+++             Field:%-24s  -> %016llX  %3d %3d [%d,%d]",
0370                  fld.first.c_str(), fld.second->mask(), fld.second->offset(), fld.second->width(),
0371                  fld.second->minValue(), fld.second->maxValue());
0372       if ( fields.empty() )   {
0373         printout(ERROR,"chkIDDescript",
0374                  "+++ FAILED   IDDescriptor: %s Found invalid [EMPTY] ID descriptor!",
0375                  id.name());
0376         ++errors;
0377         return 0;
0378       }
0379       return 1;
0380     }
0381 
0382     size_t checkLimitset(LimitSet ls)   {
0383       printout(INFO,"chkLimitSet","+++ Checking Limits:  %s Num.Limiits:%ld",
0384                ls.name(), ls.limits().size());
0385       return 1;
0386     }
0387 
0388     size_t checkRegion(Region ls)   {
0389       printout(INFO,"chkRegion","+++ Checking Limits:  %s Num.Limiits:%ld",
0390                ls.name(), ls.limits().size());
0391       return 1;
0392     }
0393 
0394     size_t checkField(CartesianField fld)   {
0395       printout(INFO,"chkField","+++ Checking Field:  %s",
0396                fld.name());
0397       return 1;
0398     }
0399     size_t checkAlignment(DetElement det)   {
0400       AlignmentCondition::Object* align = det->nominal.ptr();
0401       if ( 0 == align )  {
0402         printout(ERROR,"chkNominals",
0403                  "+++ ERROR +++ Detector element with invalid nominal:%s",
0404                  det.path().c_str());
0405         ++errors;
0406       }
0407       else if ( 0 == align->alignment_data )  {
0408         printout(ERROR,"chkNominals",
0409                  "+++ ERROR +++ Detector element with invalid nominal data:%s",
0410                  det.path().c_str());
0411         ++errors;
0412       }
0413       else if ( Condition(align).data().ptr() != align->alignment_data )  {
0414         printout(ERROR,"chkNominals",
0415                  "+++ ERROR +++ Detector element with inconsisten nominal data:%s [%p != %p]",
0416                  det.path().c_str(),Condition(align).data().ptr(),align->alignment_data);
0417         ++errors;
0418       }
0419       else  {
0420         return 1;
0421       }
0422       return 0;
0423     }
0424     
0425     /// Check nominal alignments of the volume manager
0426     size_t checkNominals(VolumeManager mgr)   {
0427       int count = 0;
0428       const auto& sdets = mgr->subdetectors;
0429       for( const auto& vm : sdets )  {
0430         VolumeManager::Object* obj   = vm.second.ptr();
0431         for( const auto& iv : obj->volumes )  {
0432           VolumeManagerContext* ctx   = iv.second;
0433           count += checkAlignment(ctx->element);
0434         }
0435       }
0436       return count;
0437     }
0438     size_t checkDetectorNominals(DetElement d)   {
0439       int count = 0;
0440       Volume v = d.placement().volume();
0441       if ( v.isSensitive() )   {
0442         count += checkAlignment(d);
0443       }
0444       for( const auto& child : d.children() )
0445         count += checkDetectorNominals(child.second);
0446       return count;
0447     }
0448   };
0449 }
0450 
0451 /// Check the collection of define statements
0452 size_t DD4hepRootCheck::checkConstants()   const   {
0453   size_t count = 0;
0454   PersistencyChecks checks;
0455   for( const auto& obj : object->constants() )
0456     count += checks.checkConstant(obj);
0457   printout(ALWAYS,"chkProperty","+++ %s Checked %ld Constant objects. Num.Errors: %ld",
0458            checks.errors==0 ? "PASSED" : "FAILED", count, checks.errors); 
0459   return checks.errors;
0460 }
0461 
0462 /// Check detector description properties (string constants)
0463 size_t DD4hepRootCheck::checkProperties()   const   { 
0464   size_t count = 0;
0465   PersistencyChecks checks;
0466   for( const auto& obj : object->properties() )
0467     count += checks.checkProperty(obj);
0468   printout(ALWAYS,"chkProperty","+++ %s Checked %ld Property objects. Num.Errors: %ld",
0469            checks.errors==0 ? "PASSED" : "FAILED", count, checks.errors); 
0470   return checks.errors;
0471 }
0472 
0473 /// Call to check a Material object
0474 size_t DD4hepRootCheck::checkMaterials()  const   {
0475   size_t count = 0;
0476   printout(ALWAYS,"chkMaterials","+++ Check not implemented. Hence OK.");
0477   return count;
0478 }
0479 
0480 /// Call to check a Readout object
0481 std::pair<std::size_t, std::size_t> DD4hepRootCheck::checkReadouts()   const   {
0482   size_t count = 0;
0483   PersistencyChecks checks;
0484   for( const auto& obj : object->readouts() )
0485     count += checks.checkReadout(obj.second);
0486 
0487   if ( object->sensitiveDetectors().size() != object->readouts().size() )   {
0488     printout(ERROR,"chkNominals",
0489              "+++ Number of sensitive detectors does NOT match number of readouts: %ld != %ld",
0490              object->sensitiveDetectors().size(),object->readouts().size());
0491     ++checks.errors;
0492   }
0493   printout(ALWAYS,"chkNominals","+++ %s Checked %ld readout objects. Num.Errors: %ld",
0494            checks.errors==0 ? "PASSED" : "FAILED", count, checks.errors);
0495   return { count, checks.errors };
0496 }
0497 
0498 /// Call to theck the DD4hep fields
0499 size_t DD4hepRootCheck::checkFields()   const   {
0500   size_t count = 0;
0501   PersistencyChecks checks;
0502   for( const auto& obj : object->fields() )
0503     count += checks.checkField(obj.second);
0504   printout(ALWAYS,"chkFields","+++ %s Checked %ld Field objects. Num.Errors: %ld",
0505            checks.errors==0 ? "PASSED" : "FAILED", count, checks.errors); 
0506   return checks.errors;
0507 }
0508 
0509 /// Call to check a Region object
0510 std::pair<std::size_t, std::size_t> DD4hepRootCheck::checkRegions()   const   {
0511   size_t count = 0;
0512   PersistencyChecks checks;
0513   for( const auto& obj : object->regions() )
0514     count += checks.checkRegion(obj.second);
0515   printout(ALWAYS,"chkRegions","+++ %s Checked %ld Region objects. Num.Errors: %ld",
0516            checks.errors==0 ? "PASSED" : "FAILED", count, checks.errors); 
0517   return { count, checks.errors };
0518 }
0519 
0520 /// Call to check an ID specification
0521 std::pair<std::size_t, std::size_t> DD4hepRootCheck::checkIdSpecs()   const   {
0522   size_t count = 0;
0523   PersistencyChecks checks;
0524   for( const auto& obj : object->idSpecifications() )
0525     count += checks.checkIDDescriptor(obj.second);
0526   printout(ALWAYS,"chkReadouts","+++ %s Checked %ld Readout objects. Num.Errors: %ld",
0527            checks.errors==0 ? "PASSED" : "FAILED", count, checks.errors); 
0528   return { count, checks.errors };
0529 }
0530 
0531 /// Call to check a top level Detector element (subdetector)
0532 std::pair<std::size_t, std::size_t> DD4hepRootCheck::checkDetectors()  const   {
0533   size_t count = 0;
0534   PersistencyChecks checks;
0535   for( const auto& obj : object->detectors() )
0536     count += checks.checkDetector(obj.second);
0537   printout(ALWAYS,"chkDetectors","+++ %s Checked %ld DetElement objects. Num.Errors: %ld",
0538            checks.errors==0 ? "PASSED" : "FAILED", count, checks.errors); 
0539   return { count, checks.errors };
0540 }
0541 
0542 /// Call to check a sensitive detector
0543 std::pair<std::size_t, std::size_t> DD4hepRootCheck::checkSensitives()   const   {
0544   size_t count = 0;
0545   PersistencyChecks checks;
0546   for( const auto& obj : object->sensitiveDetectors() )
0547     count += checks.checkSensitive(obj.second);
0548   printout(ALWAYS,"chkSensitives","+++ %s Checked %ld SensitiveDetector objects. Num.Errors: %ld",
0549            checks.errors==0 ? "PASSED" : "FAILED", count, checks.errors); 
0550   return { count, checks.errors };
0551 }
0552 
0553 /// Call to check a limit-set object
0554 std::pair<std::size_t, std::size_t> DD4hepRootCheck::checkLimitSets()   const   {
0555   PersistencyChecks checks;
0556   size_t count = 0;
0557   for( const auto& obj : object->limitsets() )
0558     count += checks.checkLimitset(obj.second);
0559   printout(ALWAYS,"chkSensitives","+++ %s Checked %ld SensitiveDetector objects. Num.Errors: %ld",
0560            checks.errors==0 ? "PASSED" : "FAILED", count, checks.errors); 
0561   return { count, checks.errors };
0562 }
0563 
0564 /// Call to check the volume manager hierarchy
0565 std::pair<std::size_t, std::size_t> DD4hepRootCheck::checkVolManager()   const   {
0566   PersistencyChecks checks;
0567   size_t count = checks.checkNominals(object->volumeManager());
0568   printout(ALWAYS,"chkNominals","+++ %s Checked %ld VolumeManager contexts. Num.Errors: %ld",
0569            checks.errors==0 ? "PASSED" : "FAILED", count, checks.errors);
0570   return { count , checks.errors };
0571 }
0572 
0573 /// Call to check the nominal alignments in the detector hierarchy (for sensitive detectors)
0574 std::pair<std::size_t, std::size_t> DD4hepRootCheck::checkNominals()   const   {
0575   size_t count = 0;
0576   PersistencyChecks checks;
0577   const auto& dets = object->sensitiveDetectors();
0578   for( const auto& d : dets )
0579     count += checks.checkDetectorNominals(object->detector(d.first));
0580   printout(ALWAYS,"chkNominals","+++ %s Checked %ld DetElements. Num.Errors: %ld",
0581            checks.errors==0 ? "PASSED" : "FAILED", count, checks.errors);
0582   return { count, checks.errors };
0583 }
0584 
0585 /// Call to check the segmentations starting from the top level detector
0586 std::pair<std::size_t, std::size_t> DD4hepRootCheck::checkSegmentations()   const   {
0587   size_t count = 0;
0588   PersistencyChecks checks;
0589   const auto& dets = object->sensitiveDetectors();
0590   for( const auto& d : dets )   {
0591     Segmentation seg = SensitiveDetector(d.second).readout().segmentation();
0592     if ( seg.isValid() )  count += checks.checkSegmentation(seg);
0593   }
0594   printout(ALWAYS,"chkNominals","+++ %s Checked %ld readout segmentations. Num.Errors: %ld",
0595            checks.errors==0 ? "PASSED" : "FAILED", count, checks.errors);
0596   return { count, checks.errors };
0597 }
0598 
0599 size_t DD4hepRootCheck::checkAll()   const   {
0600   size_t count = 0;
0601   PersistencyChecks checks;
0602 
0603   count += checkMaterials();
0604   for( const auto& obj : object->properties() )
0605     count += checks.checkProperty(obj);
0606   for( const auto& obj : object->constants() )
0607     count += checks.checkConstant(obj);
0608   for( const auto& obj : object->limitsets() )
0609     count += checks.checkLimitset(obj.second);
0610   for( const auto& obj : object->fields() )
0611     count += checks.checkField(obj.second);
0612   for( const auto& obj : object->regions() )
0613     count += checks.checkRegion(obj.second);
0614   for( const auto& obj : object->idSpecifications() )
0615     count += checks.checkIDDescriptor(obj.second);
0616   for( const auto& obj : object->detectors() )
0617     count += checks.checkDetector(obj.second);
0618   for( const auto& obj : object->sensitiveDetectors() )
0619     count += checks.checkSensitive(obj.second);
0620 
0621   count += checkVolManager().first;
0622   printout(ALWAYS,"chkAll","+++ Checked %ld objects. Num.Errors:%ld",
0623            count, checks.errors);
0624   return count;
0625 }