Warning, file /DD4hep/DDCore/src/plugins/DetectorChecksum.cpp was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <DD4hep/Plugins.h>
0016 #include <DD4hep/Printout.h>
0017 #include <DD4hep/FieldTypes.h>
0018 #include <DD4hep/DetectorTools.h>
0019 #include <DD4hep/MatrixHelpers.h>
0020 #include <DD4hep/AlignmentData.h>
0021 #include <DD4hep/DetFactoryHelper.h>
0022 #include <DD4hep/detail/ObjectsInterna.h>
0023 #include <DD4hep/detail/DetectorInterna.h>
0024 #include "DetectorChecksum.h"
0025
0026
0027 #include <TROOT.h>
0028 #include <TClass.h>
0029 #include <TColor.h>
0030 #include <TGeoBoolNode.h>
0031 #include <TGeoSystemOfUnits.h>
0032
0033
0034 #include <iostream>
0035 #include <sstream>
0036 #include <fstream>
0037 #include <iomanip>
0038 #include <cfloat>
0039 #include <cfenv>
0040
0041 using namespace dd4hep;
0042 using DetectorChecksum = dd4hep::detail::DetectorChecksum;
0043
0044 namespace {
0045
0046 bool is_volume(const TGeoVolume* volume) {
0047 Volume v(volume);
0048 return v.data() != 0;
0049 }
0050 inline double check_null(double d) {
0051 if ( fabs(d) < 1e-12 )
0052 return 0e0;
0053 else
0054 return d;
0055 }
0056 template <typename O, typename C, typename F> void handle(const O* o, const C& c, F pmf) {
0057 for (typename C::const_iterator i = c.begin(); i != c.end(); ++i) {
0058 (o->*pmf)(*i);
0059 }
0060 }
0061 template <typename T>
0062 void _do_output(const std::string& title, bool reorder, bool with_file, bool have_hash, const T& container) {
0063 std::ofstream out;
0064 std::string tit = title + ":";
0065 char delim = have_hash ? '\'' : ' ';
0066 std::string fname = title + "s.txt";
0067
0068 if ( with_file ) {
0069 out.open(fname, std::ios::out);
0070 }
0071 if ( reorder ) {
0072 std::map<DetectorChecksum::hash_t, const DetectorChecksum::entry_t*> m;
0073 for(const auto& e : container)
0074 m.emplace(e.second.hash, &e.second);
0075
0076 for(const auto& e : m) {
0077 auto data = format(nullptr, "+++ %-12s0x%016lx %c%s%c",
0078 tit.c_str(), e.second->hash, delim, have_hash ? e.second->data.c_str() : "", delim);
0079 printout(ALWAYS, "DetectorChecksum", data.c_str());
0080 if ( with_file ) out << data << std::endl;
0081 }
0082 return;
0083 }
0084 for(const auto& e : container) {
0085 auto data = format(nullptr, "+++ %-12s0x%016lx %c%s%c",
0086 tit.c_str(), e.second.hash, delim, have_hash ? e.second.data.c_str() : "", delim);
0087 printout(ALWAYS, "DetectorChecksum", data.c_str());
0088 if ( with_file ) out << data << std::endl;
0089 }
0090 }
0091 template <typename T>
0092 void _do_output_name(const std::string& title, bool reorder, bool with_file, bool have_hash, const T& container) {
0093 std::ofstream out;
0094 std::string tit = title + ":";
0095 char delim = have_hash ? '\'' : ' ';
0096 std::string fname = title + "s.txt";
0097
0098 if ( with_file ) {
0099 out.open(fname, std::ios::out);
0100 }
0101 if ( reorder ) {
0102 std::map<DetectorChecksum::hash_t, const DetectorChecksum::entry_t*> m;
0103 std::map<DetectorChecksum::hash_t, typename T::key_type> v;
0104 for(const auto& e : container) {
0105 v.emplace(e.second.hash, e.first);
0106 m.emplace(e.second.hash, &e.second);
0107 }
0108 for(const auto& e : m) {
0109 auto data = format(nullptr, "+++ %-12s0x%016lx %-32s %c%s%c",
0110 tit.c_str(), e.second->hash, v[e.first].name(),
0111 delim, have_hash ? e.second->data.c_str() : "", delim);
0112 printout(ALWAYS, "DetectorChecksum", data.c_str());
0113 if ( with_file ) out << data << std::endl;
0114 }
0115 return;
0116 }
0117 for(const auto& e : container) {
0118 auto data = format(nullptr, "+++ %-12s0x%016lx %-32s %c%s%c",
0119 tit.c_str(), e.second.hash, e.first.name(),
0120 delim, have_hash ? e.second.data.c_str() : "", delim);
0121 printout(ALWAYS, "DetectorChecksum", data.c_str());
0122 if ( with_file ) out << data << std::endl;
0123 }
0124 }
0125 }
0126
0127
0128 DetectorChecksum::DetectorChecksum(Detector& description)
0129 : m_detDesc(description), m_dataPtr(0) {
0130 }
0131
0132 DetectorChecksum::~DetectorChecksum() {
0133 if (m_dataPtr)
0134 delete m_dataPtr;
0135 m_dataPtr = 0;
0136 }
0137
0138 template <typename T> std::string DetectorChecksum::refName(T handle) const {
0139 std::string nam = handle->GetName();
0140 std::size_t idx = nam.find("_0x");
0141 if ( idx == std::string::npos ) return nam;
0142 return nam.substr(0, idx);
0143 }
0144
0145 template <> std::string DetectorChecksum::refName(Segmentation handle) const {
0146 std::string nam = handle->name();
0147 std::size_t idx = nam.find("_0x");
0148 if ( idx == std::string::npos ) return nam;
0149 return nam.substr(0, idx);
0150 }
0151
0152 template <typename T> std::string DetectorChecksum::attr_name(T handle) const {
0153 std::string n = " name=\"" + refName(handle)+"\"";
0154 return n;
0155 }
0156
0157 std::stringstream DetectorChecksum::logger() const {
0158 std::stringstream log;
0159 log.setf(std::ios::fixed, std::ios::floatfield);
0160 log << std::setprecision(precision);
0161 return log;
0162 }
0163
0164 DetectorChecksum::entry_t DetectorChecksum::make_entry(std::stringstream& log) const {
0165 std::string data(log.str());
0166 hash_t hash_value = hash64(data.c_str(), data.length());
0167 if ( have_hash_strings )
0168 return { hash_value, std::move(data) };
0169 return { hash_value, std::string("") };
0170 }
0171
0172 void DetectorChecksum::configure() {
0173 m_len_unit = _toDouble(m_len_unit_nam);
0174 m_ang_unit = _toDouble(m_ang_unit_nam)/_toDouble("deg/rad");
0175 m_ene_unit = _toDouble(m_ene_unit_nam);
0176 m_densunit = _toDouble(m_densunit_nam)/_toDouble("g/cm3");
0177 m_atomunit = _toDouble(m_atomunit_nam)/_toDouble("g/mole");
0178 if ( debug > 1 ) {
0179 printout(INFO,"DetectorChecksum","+++ Float precision: %d", precision);
0180 printout(INFO,"DetectorChecksum","+++ Unit of length: %-12s -> conversion factor: %f", m_len_unit_nam.c_str(), m_len_unit);
0181 printout(INFO,"DetectorChecksum","+++ Unit of angle: %-12s -> conversion factor: %f", m_ang_unit_nam.c_str(), m_ang_unit);
0182 printout(INFO,"DetectorChecksum","+++ Unit of energy: %-12s -> conversion factor: %f", m_ene_unit_nam.c_str(), m_ene_unit);
0183 printout(INFO,"DetectorChecksum","+++ Unit of density: %-12s -> conversion factor: %f", m_densunit_nam.c_str(), m_densunit);
0184 printout(INFO,"DetectorChecksum","+++ Unit of density: %-12s -> conversion factor: %f", m_atomunit_nam.c_str(), m_atomunit);
0185 }
0186 }
0187
0188
0189 const DetectorChecksum::entry_t& DetectorChecksum::handleElement(Atom element) const {
0190 auto& geo = data().mapOfElements;
0191 auto iel = geo.find(element);
0192 if ( iel == geo.end() ) {
0193 if ( element->HasIsotopes() ) {
0194 except("DetectorChecksum","%s: Atoms with isotopes not implemented", element.name());
0195 }
0196 else {
0197 std::stringstream log = logger();
0198 log << "<element" << attr_name(element)
0199 << " Z=\"" << element->Z() << "\""
0200 << " formula=\"" << element.name() << "\""
0201 << ">" << newline
0202 << " <atom unit=\"" << m_atomunit_nam
0203 << "\" value=\"" << std::scientific << element->A()/m_atomunit << "\"/>" << newline
0204 << "</element>";
0205 iel = geo.emplace(element, make_entry(log) ).first;
0206 }
0207 }
0208 return iel->second;
0209 }
0210
0211
0212 const DetectorChecksum::entry_t& DetectorChecksum::handleMaterial(Material medium) const {
0213 auto& geo = data().mapOfMaterials;
0214 auto ima = geo.find(medium);
0215 if ( ima == geo.end() ) {
0216 std::stringstream log = logger();
0217 auto* mat = medium->GetMaterial();
0218 log << "<material" << attr_name(medium) << "\"/>" << newline;
0219 if ( mat->IsMixture() ) {
0220 std::map<std::string, double> elts;
0221 TGeoMixture* mix = (TGeoMixture*)mat;
0222 int count_elts = mix->GetNelements();
0223 for ( Int_t idx = 0; idx < count_elts; idx++ )
0224 elts[refName(mix->GetElement(idx))] = mix->GetWmixt()[idx];
0225 log << " <elements count=\""<< count_elts << "\">" << newline;
0226 for( const auto& w : elts )
0227 log << " <fraction ref=\"" << w.first << "\" n=\"" << w.second << "\">" << newline;
0228 log << " </elements>" << newline;
0229 }
0230 else {
0231 log << " A=\"" << mat->GetA() << "\""
0232 << " Z=\"" << mat->GetZ() << "\">" << newline
0233 << " <element=\"" << refName(mat->GetElement()) << "\"/>" << newline
0234 << " <atom unit=\"" << m_atomunit_nam << "\" value=\"" << mat->GetA()/m_atomunit << "\"/>" << newline;
0235 }
0236 log << " <D unit=\"" << m_densunit_nam << "\" value=\"" << mat->GetDensity()/m_densunit << "\"/>" << newline;
0237 log << "</material>";
0238 ima = geo.emplace(medium, make_entry(log)).first;
0239 }
0240 return ima->second;
0241 }
0242
0243
0244 const DetectorChecksum::entry_t& DetectorChecksum::handleSolid(Solid solid) const {
0245 auto& geo = data().mapOfSolids;
0246 auto iso = geo.find(solid);
0247 if ( iso == geo.end() ) {
0248 const TGeoShape* shape = solid.ptr();
0249 auto log = logger();
0250
0251 if ( !shape ) {
0252 log << "<shape type=\"INVALID\"></shape>)";
0253 iso = geo.emplace(solid, make_entry(log)).first;
0254 return iso->second;
0255 }
0256
0257
0258
0259
0260 TClass* cl = shape->IsA();
0261 std::string nam = "";
0262 if ( cl == TGeoBBox::Class() ) {
0263 TGeoBBox* sh = (TGeoBBox*) shape;
0264 log << "<box" << nam
0265 << " lunit=\"" << m_len_unit_nam << "\""
0266 << " x=\"" << 2.0*sh->GetDX()/m_len_unit << "\""
0267 << " y=\"" << 2.0*sh->GetDY()/m_len_unit << "\""
0268 << " z=\"" << 2.0*sh->GetDZ()/m_len_unit << "\""
0269 << "/>";
0270 }
0271 else if ( cl == TGeoHalfSpace::Class() ) {
0272 TGeoHalfSpace* sh = (TGeoHalfSpace*)(const_cast<TGeoShape*>(shape));
0273 const auto& pnt = sh->GetPoint();
0274 const auto& nrm = sh->GetNorm();
0275 log << "<halfspace" << nam
0276 << " lunit=\"" << m_len_unit_nam << "\">" << newline
0277 << " <point x=\"" << pnt[0]/m_len_unit << "\""
0278 << " y=\"" << pnt[1]/m_len_unit << "\""
0279 << " z=\"" << pnt[2]/m_len_unit << "\"/>" << newline
0280 << " <normal x=\"" << nrm[0]/m_len_unit << "\""
0281 << " y=\"" << nrm[1]/m_len_unit << "\""
0282 << " z=\"" << nrm[2]/m_len_unit << "\"/>" << newline
0283 << "</halfspace>";
0284 }
0285 else if ( cl == TGeoTube::Class() || cl == TGeoTubeSeg::Class() ) {
0286 const TGeoTube* sh = (const TGeoTube*) shape;
0287 log << "<tube" << nam
0288 << " lunit=\"" << m_len_unit_nam << "\""
0289 << " aunit=\"" << m_ang_unit_nam << "\""
0290 << " rmin=\"" << check_null(sh->GetRmin()/m_len_unit) << "\""
0291 << " rmax=\"" << check_null(sh->GetRmax()/m_len_unit) << "\""
0292 << " dz=\"" << check_null(2*sh->GetDz()/m_len_unit) << "\""
0293 << " startphi=\"" << 0.0 << "\""
0294 << " deltaphi=\"" << 360.0/m_ang_unit << "\""
0295 << "/>";
0296 }
0297 else if ( cl == TGeoTubeSeg::Class() ) {
0298 const TGeoTubeSeg* sh = (const TGeoTubeSeg*) shape;
0299 log << "<tube" << nam
0300 << " lunit=\"" << m_len_unit_nam << "\""
0301 << " aunit=\"" << m_ang_unit_nam << "\""
0302 << " rmin=\"" << check_null(sh->GetRmin()/m_len_unit) << "\""
0303 << " rmax=\"" << check_null(sh->GetRmax()/m_len_unit) << "\""
0304 << " dz=\"" << check_null(2*sh->GetDz()/m_len_unit) << "\""
0305 << " startphi=\"" << sh->GetPhi1()/m_ang_unit << "\""
0306 << " deltaphi=\"" << (sh->GetPhi2() - sh->GetPhi1())/m_ang_unit << "\""
0307 << "/>";
0308 }
0309 else if ( cl == TGeoCtub::Class() ) {
0310 const TGeoCtub* sh = (const TGeoCtub*) shape;
0311 const Double_t* hi = sh->GetNhigh();
0312 const Double_t* lo = sh->GetNlow();
0313 log << "<cutTube" << nam
0314 << " lunit=\"" << m_len_unit_nam << "\""
0315 << " aunit=\"" << m_ang_unit_nam << "\""
0316 << " rmin=\"" << sh->GetRmin()/m_len_unit << "\""
0317 << " rmax=\"" << sh->GetRmax()/m_len_unit << "\""
0318 << " dz=\"" << 2*sh->GetDz()/m_len_unit << "\""
0319 << " startphi=\"" << sh->GetPhi1()/m_ang_unit << "\""
0320 << " deltaphi=\"" << (sh->GetPhi2() - sh->GetPhi1())/m_ang_unit << "\""
0321 << " lowX=\"" << lo[0]/m_len_unit << "\""
0322 << " lowY=\"" << lo[1]/m_len_unit << "\""
0323 << " lowZ=\"" << lo[2]/m_len_unit << "\""
0324 << " highX=\"" << hi[0]/m_len_unit << "\""
0325 << " highY=\"" << hi[1]/m_len_unit << "\""
0326 << " highZ=\"" << hi[2]/m_len_unit << "\""
0327 << "/>";
0328 }
0329 else if ( cl == TGeoEltu::Class() ) {
0330 const TGeoEltu* sh = (const TGeoEltu*) shape;
0331 log << "<eltube" << nam
0332 << " lunit=\"" << m_len_unit_nam << "\""
0333 << " dx=\"" << sh->GetA()/m_len_unit << "\""
0334 << " dy=\"" << sh->GetB()/m_len_unit << "\""
0335 << " dz=\"" << sh->GetDz()/m_len_unit << "\""
0336 << "/>";
0337 }
0338 else if ( cl == TGeoTrd1::Class() ) {
0339 const TGeoTrd1* sh = (const TGeoTrd1*) shape;
0340 log << "<trd" << nam
0341 << " lunit=\"" << m_len_unit_nam << "\""
0342 << " x1=\"" << 2*check_null(sh->GetDx1()/m_len_unit) << "\""
0343 << " x2=\"" << 2*check_null(sh->GetDx2()/m_len_unit) << "\""
0344 << " y1=\"" << 2*check_null(sh->GetDy()/m_len_unit) << "\""
0345 << " y2=\"" << 2*check_null(sh->GetDy()/m_len_unit) << "\""
0346 << " z=\"" << 2*check_null(sh->GetDz()/m_len_unit) << "\""
0347 << "/>";
0348 }
0349 else if ( cl == TGeoTrd2::Class() ) {
0350 const TGeoTrd2* sh = (const TGeoTrd2*) shape;
0351 log << "<trd" << nam
0352 << " lunit=\"" << m_len_unit_nam << "\""
0353 << " x1=\"" << 2*check_null(sh->GetDx1()/m_len_unit) << "\""
0354 << " x2=\"" << 2*check_null(sh->GetDx2()/m_len_unit) << "\""
0355 << " y1=\"" << 2*check_null(sh->GetDy1()/m_len_unit) << "\""
0356 << " y2=\"" << 2*check_null(sh->GetDy2()/m_len_unit) << "\""
0357 << " z=\"" << 2*check_null(sh->GetDz()/m_len_unit) << "\""
0358 << "/>";
0359 }
0360 else if ( cl == TGeoTrap::Class() ) {
0361 const TGeoTrap* sh = (const TGeoTrap*) shape;
0362 log << "<trap" << nam
0363 << " lunit=\"" << m_len_unit_nam << "\""
0364 << " aunit=\"" << m_ang_unit_nam << "\""
0365 << " z=\"" << check_null(2*sh->GetDz()/m_len_unit) << "\""
0366 << " theta=\"" << check_null(sh->GetTheta()/m_ang_unit) << "\""
0367 << " phi=\"" << check_null(sh->GetPhi()/m_ang_unit) << "\""
0368 << " x1=\"" << check_null(2*sh->GetBl1()/m_len_unit) << "\""
0369 << " x2=\"" << check_null(2*sh->GetTl1()/m_len_unit) << "\""
0370 << " x3=\"" << check_null(2*sh->GetBl2()/m_len_unit) << "\""
0371 << " x4=\"" << check_null(2*sh->GetTl2()/m_len_unit) << "\""
0372 << " y1=\"" << check_null(2*sh->GetH1()/m_len_unit) << "\""
0373 << " y2=\"" << check_null(2*sh->GetH2()/m_len_unit) << "\""
0374 << " alpha1=\"" << check_null(sh->GetAlpha1()/m_ang_unit) << "\""
0375 << " alpha2=\"" << check_null(sh->GetAlpha2()/m_ang_unit) << "\""
0376 << "/>";
0377 }
0378 else if ( cl == TGeoHype::Class() ) {
0379 const TGeoHype* sh = (const TGeoHype*) shape;
0380 log << "<hype" << nam
0381 << " lunit=\"" << m_len_unit_nam << "\""
0382 << " aunit=\"" << m_ang_unit_nam << "\""
0383 << " rmin=\"" << check_null(sh->GetRmin()/m_len_unit) << "\""
0384 << " rmax=\"" << check_null(sh->GetRmax()/m_len_unit) << "\""
0385 << " inst=\"" << check_null(sh->GetStIn()/m_ang_unit) << "\""
0386 << " outst=\"" << check_null(sh->GetStOut()/m_ang_unit) << "\""
0387 << " z=\"" << check_null(2*sh->GetDz()/m_len_unit) << "\""
0388 << "/>";
0389 }
0390 else if ( cl == TGeoPgon::Class() ) {
0391 const TGeoPgon* sh = (const TGeoPgon*) shape;
0392 log << "<polyhedra" << nam
0393 << " lunit=\"" << m_len_unit_nam << "\""
0394 << " aunit=\"" << m_ang_unit_nam << "\""
0395 << " startphi=\"" << check_null(sh->GetPhi1()/m_ang_unit) << "\""
0396 << " deltaphi=\"" << check_null(sh->GetDphi()/m_ang_unit) << "\""
0397 << " numsides=\"" << sh->GetNedges() << "\">" << newline;
0398 for(int i=0, n=sh->GetNz(); i<n; ++i) {
0399 log << " <zplane z=\"" << check_null(sh->GetZ(i)/m_len_unit)
0400 << "\" rmin=\"" << check_null(sh->GetRmin(i)/m_len_unit) << "\""
0401 << "\" rmax=\"" << check_null(sh->GetRmax(i)/m_len_unit) << "\"/>" << newline;
0402 }
0403 log << "</polyhedra>";
0404 }
0405 else if ( cl == TGeoPcon::Class() ) {
0406 const TGeoPcon* sh = (const TGeoPcon*) shape;
0407 log << "<polycone" << nam
0408 << " lunit=\"" << m_len_unit_nam << "\""
0409 << " aunit=\"" << m_ang_unit_nam << "\""
0410 << " startphi=\"" << check_null(sh->GetPhi1()/m_ang_unit) << "\""
0411 << " deltaphi=\"" << check_null(sh->GetDphi()/m_ang_unit) << "\">" << newline;
0412 for(int i=0, n=sh->GetNz(); i<n; ++i) {
0413 log << " <zplane z=\"" << check_null(sh->GetZ(i)/m_len_unit)
0414 << "\" rmin=\"" << check_null(sh->GetRmin(i)/m_len_unit) << "\""
0415 << "\" rmax=\"" << check_null(sh->GetRmax(i)/m_len_unit) << "\"/>" << newline;
0416 }
0417 log << "</polycone>";
0418 }
0419 else if ( cl == TGeoCone::Class() ) {
0420 const TGeoCone* sh = (const TGeoCone*) shape;
0421 log << "<cone" << nam
0422 << " lunit=\"" << m_len_unit_nam << "\""
0423 << " aunit=\"" << m_ang_unit_nam << "\""
0424 << " rmin1=\"" << check_null(sh->GetRmin1()/m_len_unit) << "\""
0425 << " rmin2=\"" << check_null(sh->GetRmin2()/m_len_unit) << "\""
0426 << " rmax1=\"" << check_null(sh->GetRmax1()/m_len_unit) << "\""
0427 << " rmax2=\"" << check_null(sh->GetRmax2()/m_len_unit) << "\""
0428 << " z=\"" << check_null(sh->GetDz()/m_len_unit) << "\""
0429 << " startphi=\"" << 0.0/m_ang_unit << "\""
0430 << " deltaphi=\"" << 360.0/m_ang_unit << "\""
0431 << "/>";
0432 }
0433 else if ( cl == TGeoConeSeg::Class() ) {
0434 const TGeoConeSeg* sh = (const TGeoConeSeg*) shape;
0435 log << "<cone" << nam
0436 << " lunit=\"" << m_len_unit_nam << "\""
0437 << " aunit=\"" << m_ang_unit_nam << "\""
0438 << " rmin1=\"" << check_null(sh->GetRmin1()/m_len_unit) << "\""
0439 << " rmin2=\"" << check_null(sh->GetRmin2()/m_len_unit) << "\""
0440 << " rmax1=\"" << check_null(sh->GetRmax1()/m_len_unit) << "\""
0441 << " rmax2=\"" << check_null(sh->GetRmax2()/m_len_unit) << "\""
0442 << " z=\"" << check_null(sh->GetDz()/m_len_unit) << "\""
0443 << " startphi=\"" << check_null(sh->GetPhi1()/m_ang_unit) << "\""
0444 << " deltaphi=\"" << check_null((sh->GetPhi1()-sh->GetPhi1())/m_ang_unit) << "\""
0445 << "/>";
0446 }
0447 else if ( cl == TGeoParaboloid::Class() ) {
0448 const TGeoParaboloid* sh = (const TGeoParaboloid*) shape;
0449 log << "<paraboloid" << nam
0450 << " lunit=\"" << m_len_unit_nam << "\""
0451 << " rlo=\"" << sh->GetRlo()/m_len_unit << "\""
0452 << " rhi=\"" << sh->GetRhi()/m_len_unit << "\""
0453 << " z=\"" << sh->GetDz()/m_len_unit << "\""
0454 << "/>";
0455 }
0456 else if ( cl == TGeoSphere::Class() ) {
0457 const TGeoSphere* sh = (const TGeoSphere*) shape;
0458 log << "<sphere" << nam
0459 << " lunit=\"" << m_len_unit_nam << "\""
0460 << " aunit=\"" << m_ang_unit_nam << "\""
0461 << " rmin=\"" << sh->GetRmin()/m_len_unit << "\""
0462 << " rmax=\"" << sh->GetRmax()/m_len_unit << "\""
0463 << " startphi=\"" << sh->GetPhi1()/m_ang_unit << "\""
0464 << " deltaphi=\"" << (sh->GetPhi1()-sh->GetPhi1())/m_ang_unit << "\""
0465 << " starttheta=\"" << sh->GetTheta1()/m_ang_unit << "\""
0466 << " deltatheta=\"" << (sh->GetTheta1()-sh->GetTheta1())/m_ang_unit << "\""
0467 << "/>";
0468 }
0469 else if ( cl == TGeoTorus::Class() ) {
0470 const TGeoTorus* sh = (const TGeoTorus*) shape;
0471 log << "<torus" << nam
0472 << " lunit=\"" << m_len_unit_nam << "\""
0473 << " aunit=\"" << m_ang_unit_nam << "\""
0474 << " rtor=\"" << sh->GetR()/m_len_unit << "\""
0475 << " rmin=\"" << sh->GetRmin()/m_len_unit << "\""
0476 << " rmax=\"" << sh->GetRmax()/m_len_unit << "\""
0477 << " startphi=\"" << sh->GetPhi1()/m_ang_unit << "\""
0478 << " deltaphi=\"" << sh->GetDphi()/m_ang_unit << "\""
0479 << "/>";
0480 }
0481 else if ( cl == TGeoArb8::Class() ) {
0482 TGeoArb8* sh = (TGeoArb8*) shape;
0483 const Double_t* v = sh->GetVertices();
0484 log << "<arb8" << nam
0485 << " v1x=\"" << v[0]/m_len_unit << "\""
0486 << " v1y=\"" << v[1]/m_len_unit << "\""
0487 << " v2x=\"" << v[2]/m_len_unit << "\""
0488 << " v2y=\"" << v[3]/m_len_unit << "\""
0489 << " v3x=\"" << v[4]/m_len_unit << "\""
0490 << " v3y=\"" << v[5]/m_len_unit << "\""
0491 << " v4x=\"" << v[6]/m_len_unit << "\""
0492 << " v4y=\"" << v[7]/m_len_unit << "\""
0493 << " v5x=\"" << v[8]/m_len_unit << "\""
0494 << " v5y=\"" << v[9]/m_len_unit << "\""
0495 << " v6x=\"" << v[10]/m_len_unit << "\""
0496 << " v6y=\"" << v[11]/m_len_unit << "\""
0497 << " v7x=\"" << v[12]/m_len_unit << "\""
0498 << " v7y=\"" << v[13]/m_len_unit << "\""
0499 << " v8x=\"" << v[14]/m_len_unit << "\""
0500 << " v8y=\"" << v[15]/m_len_unit << "\""
0501 << " dz=\"" << sh->GetDz()/m_len_unit << "\""
0502 << "/>";
0503 }
0504 else if ( cl == TGeoXtru::Class() ) {
0505 const TGeoXtru* sh = (const TGeoXtru*) shape;
0506 log << "<xtru" << nam << ">" << newline;
0507 for (int i = 0; i < sh->GetNvert(); i++) {
0508 log << " <twoDimVertex x=\"" << sh->GetX(i)/m_len_unit << "\""
0509 << "\" y=\"" << sh->GetY(i)/m_len_unit << "\"/>" << newline;
0510 }
0511 for (int i = 0; i < sh->GetNz(); i++) {
0512 log << " <section zOrder=\"" << i << "\""
0513 << " scalingFactor=\"" << sh->GetScale(i) << "\""
0514 << " zPosition=\"" << sh->GetZ(i)/m_len_unit << "\""
0515 << " xOffset=\"" << sh->GetXOffset(i)/m_len_unit << "\""
0516 << " yOffset=\"" << sh->GetYOffset(i)/m_len_unit << "\"/>" << newline;
0517 }
0518 log << "</xtru>";
0519 }
0520 else if (shape->IsA() == TGeoCompositeShape::Class() ) {
0521 const TGeoCompositeShape* sh = (const TGeoCompositeShape*)shape;
0522 const TGeoBoolNode* boolean = sh->GetBoolNode();
0523 const TGeoShape* left = boolean->GetLeftShape();
0524 const TGeoShape* right = boolean->GetRightShape();
0525 const TGeoMatrix* mat_left = boolean->GetLeftMatrix();
0526 const TGeoMatrix* mat_right = boolean->GetRightMatrix();
0527 std::string str_oper;
0528
0529 TGeoBoolNode::EGeoBoolType oper = boolean->GetBooleanOperator();
0530 if (oper == TGeoBoolNode::kGeoSubtraction)
0531 str_oper = "subtraction";
0532 else if (oper == TGeoBoolNode::kGeoUnion)
0533 str_oper = "union";
0534 else if (oper == TGeoBoolNode::kGeoIntersection)
0535 str_oper = "intersection";
0536
0537 if ( left->IsA() == TGeoScaledShape::Class() && right->IsA() == TGeoBBox::Class() ) {
0538 const auto* scaled = (TGeoScaledShape*)left;
0539 const auto* sphere = (TGeoSphere*)scaled->GetShape();
0540 const auto* box = (TGeoBBox*)right;
0541 if ( scaled->IsA() == TGeoSphere::Class() && oper == TGeoBoolNode::kGeoIntersection ) {
0542 Double_t sx = scaled->GetScale()->GetScale()[0];
0543 Double_t sy = scaled->GetScale()->GetScale()[1];
0544 Double_t ax = sx * sphere->GetRmax();
0545 Double_t by = sy * sphere->GetRmax();
0546 Double_t cz = sphere->GetRmax();
0547 Double_t dz = box->GetDZ();
0548 Double_t zorig = box->GetOrigin()[2];
0549 Double_t zcut2 = dz + zorig;
0550 Double_t zcut1 = 2 * zorig - zcut2;
0551 log << "<ellipsoid" << nam
0552 << " lunit=\"" << m_len_unit_nam << "\""
0553 << " ax=\"" << ax/m_len_unit << "\""
0554 << " by=\"" << by/m_len_unit << "\""
0555 << " cz=\"" << cz/m_len_unit << "\""
0556 << " zcut1=\"" << zcut1/m_len_unit << "\""
0557 << " zcut2=\"" << zcut2/m_len_unit << "\"/>";
0558 iso = geo.emplace(solid, make_entry(log)).first;
0559 return iso->second;
0560 }
0561 }
0562
0563
0564 const entry_t& ent_left = handleSolid(Solid(left));
0565 const entry_t& ent_right = handleSolid(Solid(right));
0566 const entry_t& ent_pos_left = handlePosition(mat_left);
0567 const entry_t& ent_rot_left = handleRotation(mat_left);
0568 const entry_t& ent_pos_right = handlePosition(mat_right);
0569 const entry_t& ent_rot_right = handleRotation(mat_right);
0570 log << "<" << str_oper << nam
0571 << " lunit=\"" << m_len_unit_nam << "\""
0572 << " aunit=\"" << m_ang_unit_nam << "\">" << newline
0573 << " <first ref=\"" << (void*)ent_left.hash << "\"" << ">" << newline
0574 << " " << ent_pos_left.hash << newline
0575 << " " << ent_rot_left.hash << newline
0576 << " </first>" << newline
0577 << " <second ref=\"" << (void*)ent_right.hash << "\"" << ">" << newline
0578 << " " << ent_pos_right.hash << newline
0579 << " " << ent_rot_right.hash << newline
0580 << " </second>" << newline
0581 << "</" << str_oper << ">";
0582 }
0583 else if ( shape->IsA() == TGeoScaledShape::Class() ) {
0584 const TGeoScaledShape* sh = (TGeoScaledShape*)shape;
0585 const TGeoShape* org = sh->GetShape();
0586 const double* scl = sh->GetScale()->GetScale();
0587 log << "<scaled_shape" << nam
0588 << " sx=\"" << scl[0] << "\""
0589 << " sy=\"" << scl[1] << "\""
0590 << " sz=\"" << scl[2] << "\">" << newline
0591 << " " << handleSolid(Solid(org)).hash << newline
0592 << "</scaled_shape>";
0593 }
0594 else if ( shape->IsA() == TGeoShapeAssembly::Class() ) {
0595 log << "<shape_assembly " << nam << "\"/>";
0596 }
0597 else if ( shape->IsA() == TGeoTessellated::Class() ) {
0598 if ( hash_meshes ) {
0599 const TGeoTessellated* sh = (TGeoTessellated*)shape;
0600 log << "<define>" << newline;
0601 if ( sh->IsClosedBody() == false ) {
0602 except("DetectorChecksum","+++ TGeoTessellated volume is not closed: %s", solid.name());
0603 }
0604 for (int ivertex = 0; ivertex < sh->GetNvertices(); ivertex++) {
0605
0606 const auto& vtx = const_cast<TGeoTessellated*>(sh)->GetVertex(ivertex);
0607 log << "<position name\"" << nam << "_v" << ivertex
0608 << " lunit=\"" << m_len_unit_nam << "\""
0609 << " x=\"" << vtx.x()/m_len_unit << "\""
0610 << " y=\"" << vtx.y()/m_len_unit << "\""
0611 << " z=\"" << vtx.z()/m_len_unit << "\""
0612 << "/>" << newline;
0613 }
0614 log << "</define>" << newline;
0615 log << "<tessellated name=\"" << nam << "\">" << newline;
0616 for (int ifacet = 0; ifacet < sh->GetNfacets(); ifacet++) {
0617
0618 const auto& facet = const_cast<TGeoTessellated*>(sh)->GetFacet(ifacet);
0619 if ( facet.GetNvert() == 3 ) {
0620 log << "<triangular";
0621 }
0622 else if ( facet.GetNvert() == 4 ) {
0623 log << "<quadrangular";
0624 }
0625 else {
0626 except("DetectorChecksum","+++ TGeoTessellated volume with unsupported number of vertices: %s", solid.name());
0627 }
0628 for (int ivertex = 0; ivertex < facet.GetNvert(); ivertex++) {
0629 #if ROOT_VERSION_CODE >= ROOT_VERSION(6,31,1)
0630 auto vertexIndex = facet[ivertex];
0631 #else
0632 auto vertexIndex = facet.GetVertexIndex(ivertex);
0633 #endif
0634 log << " vertex" << ivertex + 1 << "=\"" << nam << "_v" << vertexIndex << "\"";
0635 }
0636 log << " type=\"ABSOLUTE\"/>" << newline;
0637 }
0638 log << "</tessellated>" << newline;
0639 }
0640 else {
0641 log << "<tessellated></tessellated>" << newline;
0642 }
0643 }
0644 else {
0645 except("DetectorChecksum","+++ Unknown shape: %s", solid.name());
0646 }
0647 auto ins = geo.emplace(solid, make_entry(log));
0648 if ( !ins.second ) {
0649 except("DetectorChecksum", "+++ FAILED to register shape: %s", solid.name());
0650 }
0651 iso = ins.first;
0652 }
0653 return iso->second;
0654 }
0655
0656
0657 const DetectorChecksum::entry_t& DetectorChecksum::handlePosition(const TGeoMatrix* trafo) const {
0658 auto& geo = data().mapOfPositions;
0659 auto ipo = geo.find(trafo);
0660 if ( ipo == geo.end() ) {
0661 const double* tr = trafo->GetTranslation();
0662 std::stringstream log = logger();
0663 log << "<position"
0664 << " unit=\"" << m_len_unit_nam << "\""
0665 << " x=\"" << check_null(tr[0]/m_len_unit) << "\""
0666 << " y=\"" << check_null(tr[1]/m_len_unit) << "\""
0667 << " z=\"" << check_null(tr[2]/m_len_unit) << "\"";
0668 log << "/>";
0669 ipo = geo.emplace(trafo, make_entry(log)).first;
0670 }
0671 return ipo->second;
0672 }
0673
0674
0675 const DetectorChecksum::entry_t& DetectorChecksum::handleRotation(const TGeoMatrix* trafo) const {
0676 auto& geo = data().mapOfRotations;
0677 auto iro = geo.find(trafo);
0678 if ( iro == geo.end() ) {
0679 XYZAngles rot = detail::matrix::_xyzAngles(trafo->GetRotationMatrix());
0680 std::stringstream log = logger();
0681 log << "<rotation"
0682 << " unit=\"" << m_ang_unit_nam << "\""
0683 << " x=\"" << check_null(rot.X()/m_ang_unit) << "\""
0684 << " y=\"" << check_null(rot.Y()/m_ang_unit) << "\""
0685 << " z=\"" << check_null(rot.Z()/m_ang_unit) << "\""
0686 << "/>";
0687 iro = geo.emplace(trafo, make_entry(log)).first;
0688 }
0689 return iro->second;
0690 }
0691
0692
0693 const DetectorChecksum::entry_t& DetectorChecksum::handleVis(VisAttr attr) const {
0694 auto& geo = data().mapOfVis;
0695 auto ivi = geo.find(attr);
0696 if ( ivi == geo.end() ) {
0697 std::stringstream log = logger();
0698 float red = 0, green = 0, blue = 0;
0699 int style = attr.lineStyle();
0700 int draw = attr.drawingStyle();
0701 attr.rgb(red, green, blue);
0702
0703 log << "<vis"
0704 << " name=\"" << attr.name() << "\""
0705 << " visible=\"" << attr.visible() << "\""
0706 << " show_daughters=\"" << attr.showDaughters() << "\"";
0707 if (style == VisAttr::SOLID)
0708 log << " line_style=\"unbroken\"";
0709 else if (style == VisAttr::DASHED)
0710 log << " line_style=\"broken\"";
0711 if (draw == VisAttr::SOLID)
0712 log << " line_style=\"solid\"";
0713 else if (draw == VisAttr::WIREFRAME)
0714 log << " line_style=\"wireframe\"";
0715 log << "<color"
0716 << " alpha=\"" << attr.alpha()
0717 << " R=\"" << red << "\""
0718 << " B=\"" << blue << "\""
0719 << " G=\"" << green << "\"/>" << newline;
0720 log << "</vis>";
0721 ivi = geo.emplace(attr, make_entry(log)).first;
0722 }
0723 return ivi->second;
0724 }
0725
0726
0727 const DetectorChecksum::entry_t& DetectorChecksum::handleRegion(Region region) const {
0728 auto& geo = data().mapOfRegions;
0729 auto ire = geo.find(region);
0730 if ( ire == geo.end() ) {
0731 std::stringstream log = logger();
0732 log << "<region name=\"" << region.name() << "\""
0733 << " store_secondaries=\"" << (region.storeSecondaries() ? 1 : 0) << "\""
0734 << " cut=\"" << region.cut() << "\""
0735 << " eunit=\"" << m_ene_unit_nam << "\""
0736 << " lunit=\"" << m_len_unit_nam << "\""
0737 << "/>";
0738 ire = geo.emplace(region, make_entry(log)).first;
0739 }
0740 return ire->second;
0741 }
0742
0743
0744 const DetectorChecksum::entry_t& DetectorChecksum::handleLimitSet(LimitSet lim) const {
0745 auto& geo = data().mapOfLimits;
0746 auto ili = geo.find(lim);
0747 if ( ili == geo.end() ) {
0748 std::stringstream log = logger();
0749 const std::set<Limit>& obj = lim.limits();
0750 log << "<limitset name=\"" << lim.name() << "\">" << newline;
0751 for (const auto& limit : obj) {
0752 log << "<limit name=\"" << limit.name << "\""
0753 << " unit=\"" << limit.unit << "\""
0754 << " value=\"" << limit.value << "\""
0755 << " particles=\"" << limit.particles << "\""
0756 << "/>" << newline;
0757 }
0758 log << "</limitSet>";
0759 ili = geo.emplace(lim, make_entry(log)).first;
0760 }
0761 return ili->second;
0762 }
0763
0764 const DetectorChecksum::entry_t& DetectorChecksum::handleAlignment(Alignment alignment) const {
0765 auto& geo = data().mapOfAlignments;
0766 auto ial = geo.find(alignment);
0767 if ( ial == geo.end() ) {
0768 std::stringstream log = logger();
0769 const auto& data = alignment.data();
0770 double x, y, z;
0771 data.delta.pivot.GetComponents(x, y, z);
0772 log << "<nominal>" << newline;
0773 log << "<translation"
0774 << " unit=\"" << m_len_unit_nam << "\""
0775 << " x=\"" << data.delta.translation.X()/m_len_unit << "\""
0776 << " y=\"" << data.delta.translation.Y()/m_len_unit << "\""
0777 << " z=\"" << data.delta.translation.Z()/m_len_unit << "\"/>" << newline;
0778 log << "<pivot"
0779 << " unit=\"" << m_len_unit_nam << "\""
0780 << " x=\"" << x / m_len_unit << "\""
0781 << " y=\"" << y / m_len_unit << "\""
0782 << " z=\"" << z / m_len_unit << "\"/>" << newline;
0783 log << "<rotation"
0784 << " unit=\"" << m_len_unit_nam << "\""
0785 << " theta=\"" << data.delta.rotation.Theta()/m_ang_unit << "\""
0786 << " phi=\"" << data.delta.rotation.Phi()/m_len_unit << "\""
0787 << " psi=\"" << data.delta.rotation.Psi()/m_len_unit << "\"/>" << newline;
0788 log << "</nominal>";
0789 ial = geo.emplace(alignment, make_entry(log)).first;
0790 }
0791 return ial->second;
0792 }
0793
0794
0795 void DetectorChecksum::collectVolume(Volume volume) const {
0796 Volume v(volume);
0797 if ( is_volume(volume) ) {
0798 Region reg = v.region();
0799 LimitSet lim = v.limitSet();
0800 VisAttr vis = v.visAttributes();
0801 SensitiveDetector det = v.sensitiveDetector();
0802 if ( lim.isValid() ) handleLimitSet(lim);
0803 if ( reg.isValid() ) handleRegion(reg);
0804 if ( vis.isValid() ) handleVis(vis);
0805 if ( det.isValid() ) handleSensitive(det);
0806 }
0807 else {
0808 printout(WARNING,"DetectorChecksum","++ CollectVolume: Skip volume: %s",volume.name());
0809 }
0810 }
0811
0812
0813 const DetectorChecksum::entry_t& DetectorChecksum::handleVolume(Volume volume) const {
0814 auto& geo = data().mapOfVolumes;
0815 auto ivo = geo.find(volume);
0816 if ( ivo == geo.end() ) {
0817 const TGeoVolume* v = volume;
0818 std::string tag;
0819 std::string sol;
0820 std::string nam = attr_name(v);
0821 std::stringstream log = logger();
0822 TGeoShape* sh = v->GetShape();
0823 if ( !sh )
0824 throw std::runtime_error("DetectorChecksum: No solid present for volume:" + nam);
0825
0826 if (v->IsAssembly()) {
0827 const auto& solid_ent = handleSolid(sh);
0828 tag = "assembly";
0829 log << "<" << tag << nam
0830 << " solid=\"" << refName(sh) << "\""
0831 << " solid_hash=\"" << (void*)solid_ent.hash << "\"";
0832 }
0833 else {
0834 TGeoMedium* med = v->GetMedium();
0835 if ( !med )
0836 throw std::runtime_error("DetectorChecksum: No material present for volume:" + nam);
0837 const auto& solid_ent = handleSolid(sh);
0838 tag = "volume";
0839 log << "<" << tag << nam
0840 << " material=\"" << refName(med) << "\""
0841 << " solid=\"" << refName(sh) << "\""
0842 << " solid_hash=\"" << (void*)solid_ent.hash << "\"";
0843 }
0844 collectVolume(volume);
0845 auto reg = volume.region();
0846 auto lim = volume.limitSet();
0847 auto vis = volume.visAttributes();
0848 auto det = volume.sensitiveDetector();
0849 if ( lim.isValid() )
0850 log << " limits=\"" << refName(lim) << "\"";
0851 if ( reg.isValid() )
0852 log << " region=\"" << refName(reg) << "\"";
0853 if ( vis.isValid() )
0854 log << " vis=\"" << refName(vis) << "\"";
0855 if ( det.isValid() )
0856 log << " sensitive=\"" << refName(det) << "\"";
0857 const TObjArray* dau = const_cast<TGeoVolume*>(v)->GetNodes();
0858 if (dau && dau->GetEntries() > 0) {
0859 log << ">" << newline;
0860 for (Int_t i = 0, n_dau = dau->GetEntries(); i < n_dau; ++i) {
0861 TGeoNode* node = reinterpret_cast<TGeoNode*>(dau->At(i));
0862 const auto& ent = handlePlacement(node);
0863 log << " <physvol name=\"" << refName(node) << " hash=\"" << (void*)ent.hash << "\"/>" << newline;
0864 }
0865 log << "</" << tag << ">";
0866 }
0867 else {
0868 log << "/>";
0869 }
0870 auto ins = geo.emplace(volume, make_entry(log));
0871 if ( !ins.second ) {
0872 except("DetectorChecksum", "+++ FAILED to register volume: %s", volume.name());
0873 }
0874 ivo = ins.first;
0875 }
0876 return ivo->second;
0877 }
0878
0879
0880 const DetectorChecksum::entry_t& DetectorChecksum::handlePlacement(PlacedVolume node) const {
0881 auto& geo = data().mapOfPlacements;
0882 auto ipl = geo.find(node);
0883 if ( ipl == geo.end() ) {
0884 TGeoMatrix* matrix = node->GetMatrix();
0885 TGeoVolume* volume = node->GetVolume();
0886 const auto& vol_ent = handleVolume(volume);
0887 std::stringstream log = logger();
0888 log << "<physvol" << attr_name(node)
0889 << " volume=\"" << refName(volume) << "\"";
0890 log << " volume_hash=\"" << (void*)vol_ent.hash << "\"";
0891 log << ">" << newline;
0892 if ( matrix ) {
0893 log << " " << handlePosition(matrix).hash << newline;
0894
0895 if ( matrix->IsRotation() ) {
0896 log << " " << handleRotation(matrix).hash << newline;
0897
0898 }
0899 }
0900 if ( node.data() ) {
0901 const auto& ids = node.volIDs();
0902 for (const auto& vid : ids )
0903 log << " <physvolid"
0904 << " name=\"" << vid.first << "\""
0905 << " value=\"" << vid.second << "\""
0906 << "/>" << newline;
0907 }
0908 log << "</physvol>";
0909 ipl = geo.emplace(node, make_entry(log)).first;
0910 }
0911 return ipl->second;
0912 }
0913
0914 const DetectorChecksum::entry_t& DetectorChecksum::handleDetElement(DetElement det) const {
0915 auto& geo = data().mapOfDetElements;
0916 auto dit = geo.find(det);
0917 if ( dit == geo.end() ) {
0918 std::stringstream log = logger();
0919 const auto& place = handlePlacement(det.placement());
0920 const auto& par = det.parent().isValid() ? handleDetElement(det.parent()) : empty_entry;
0921 log << "<detelement"
0922 << " name=\"" << det.name() << "\""
0923 << " id=\"" << det.id() << "\""
0924 << " type=\"" << det.type() << "\""
0925 << " key=\"" << det.key() << "\""
0926 << " parent=\"" << (void*)par.hash << "\""
0927 << " flag=\"" << det.typeFlag() << "\""
0928 << " combineHits=\"" << det.combineHits() << "\""
0929 << " placement=\"" << (void*)place.hash << "\""
0930 << "/>";
0931 dit = geo.emplace(det, make_entry(log)).first;
0932 }
0933 return dit->second;
0934 }
0935
0936
0937 const DetectorChecksum::entry_t& DetectorChecksum::handleSensitive(SensitiveDetector sd) const {
0938 if ( sd.isValid() ) {
0939 auto& geo = data().mapOfSensDets;
0940 auto isi = geo.find(sd);
0941 if ( isi == geo.end() ) {
0942 std::stringstream log = logger();
0943 log << "<sensitive_detector"
0944 << " name=\"" << refName(sd) << "\""
0945 << " type=\"" << sd.type() << "\""
0946 << " ecut=\"" << sd.energyCutoff()/m_ene_unit << "\""
0947 << " eunit=\"" << m_ene_unit_nam << "\""
0948 << " hits_collection=\"" << sd.hitsCollection() << "\""
0949 << " combine_hits=\"" << sd.combineHits() << "\"";
0950 Readout ro = sd.readout();
0951 if ( ro.isValid() ) {
0952 const auto& ro_ent = handleIdSpec(ro.idSpec());
0953 log << " iddescriptor=\"" << (void*)ro_ent.hash << "\"";
0954 const auto& seg_ent = handleSegmentation(ro.segmentation());
0955 log << " segmentation=\"" << (void*)seg_ent.hash << "\"";
0956 }
0957 log << "/>";
0958 isi = geo.emplace(sd, make_entry(log)).first;
0959 }
0960 return isi->second;
0961 }
0962 return empty_entry;
0963 }
0964
0965
0966 const DetectorChecksum::entry_t& DetectorChecksum::handleSegmentation(Segmentation seg) const {
0967 if (seg.isValid()) {
0968 auto& geo = data().mapOfSegmentations;
0969 auto ise = geo.find(seg);
0970 if ( ise == geo.end() ) {
0971 using param_t = DDSegmentation::SegmentationParameter;
0972 std::stringstream log = logger();
0973 const auto& p = seg.parameters();
0974 log << "<segmentation" << attr_name(seg)
0975 << " type=\"" << seg.type() << "\">" << newline;
0976 log << " <parameters>" << newline;
0977 for ( const auto& v : p ) {
0978 log << " <parameter";
0979 log << " name=\"" << v->name() << "\""
0980 << " type=\"" << v->type() << "\"";
0981 if ( v->unitType() == param_t::LengthUnit )
0982 log << " value=\"" << _toDouble(v->value())/m_len_unit << "\""
0983 << " unit=\"" << m_len_unit_nam << "\"";
0984 else if ( v->unitType() == param_t::AngleUnit )
0985 log << " value=\"" << _toDouble(v->value())/m_ang_unit << "\""
0986 << " unit=\"" << m_ang_unit_nam << "\"";
0987 else
0988 log << " value=\"" << v->value() << "\"";
0989 log << "/>" << newline;
0990 }
0991 log << " </parameters>" << newline;
0992 log << "</segmentation>";
0993 ise = geo.emplace(seg, make_entry(log)).first;
0994 }
0995 return ise->second;
0996 }
0997 return empty_entry;
0998 }
0999
1000
1001 const DetectorChecksum::entry_t& DetectorChecksum::handleIdSpec(IDDescriptor id_spec) const {
1002 if ( id_spec.isValid() ) {
1003 auto& geo = data().mapOfIdSpecs;
1004 auto iid = geo.find(id_spec);
1005 if ( iid == geo.end() ) {
1006 const IDDescriptor::FieldMap& fm = id_spec.fields();
1007 std::stringstream log = logger();
1008 log << "<id name=\"" << refName(id_spec) << "\">" << newline;
1009 for (const auto& i : fm ) {
1010 const BitFieldElement* f = i.second;
1011 log << " <idfield label=\"" << f->name() << "\""
1012 << " signed=\"" << true_false(f->isSigned()) << "\""
1013 << " length=\"" << f->width() << "\""
1014 << " start=\"" << f->offset() << "\"/>" << newline;
1015 }
1016 log << "</id>";
1017 iid = geo.emplace(id_spec, make_entry(log)).first;
1018 }
1019 return iid->second;
1020 }
1021 return empty_entry;
1022 }
1023
1024
1025 const DetectorChecksum::entry_t& DetectorChecksum::handleField(OverlayedField f) const {
1026 auto& geo = data().mapOfFields;
1027 auto ifd = geo.find(f);
1028 if ( ifd == geo.end() ) {
1029 std::string type = f->GetTitle();
1030 std::stringstream log = logger();
1031 log << "<field name=\"" << f->GetName() << "\" type=\"" << f->GetTitle() << "\">";
1032 #if 0
1033 field = xml_elt_t(geo.doc, Unicode(type));
1034 field.setAttr(_U(name), f->GetName());
1035 fld = PluginService::Create<NamedObject*>(type + "_Convert2Detector", &m_detDesc, &field, &fld);
1036 printout(ALWAYS,"DetectorChecksum","++ %s electromagnetic field:%s of type %s",
1037 (fld.isValid() ? "Converted" : "FAILED to convert "), f->GetName(), type.c_str());
1038 if (!fld.isValid()) {
1039 PluginDebug dbg;
1040 PluginService::Create<NamedObject*>(type + "_Convert2Detector", &m_detDesc, &field, &fld);
1041 throw std::runtime_error("Failed to locate plugin to convert electromagnetic field:"
1042 + std::string(f->GetName()) + " of type " + type + ". "
1043 + dbg.missingFactory(type));
1044 }
1045 #endif
1046 log << "</field>";
1047 ifd = geo.emplace(f, make_entry(log)).first;
1048 }
1049 return ifd->second;
1050 }
1051
1052
1053 const DetectorChecksum::entry_t& DetectorChecksum::handleHeader() const {
1054 GeometryInfo& geo = data();
1055 Header hdr = m_detDesc.header();
1056 if ( hdr.isValid() && 0 == geo.header.hash ) {
1057 std::stringstream log = logger();
1058 log << "<header name=\"" << hdr.name() << "\">"
1059 << "<autor name=\"" << hdr.author() << "\"/>"
1060 << "<generator version=\"" << hdr.version() << "\"" << " url=\"" << hdr.url() << "\"/>"
1061 << "<comment>" << hdr.comment() << "</comment>"
1062 << "</header>";
1063 geo.header = make_entry(log);
1064 return geo.header;
1065 }
1066 printout(WARNING,"DetectorChecksum","+++ No Detector header information availible from the geometry description.");
1067 return empty_entry;
1068 }
1069
1070 void DetectorChecksum::collect_det_elements(DetElement top) const {
1071 auto& geo = data().mapOfDetElements;
1072 auto it = geo.find(top);
1073 if ( it == geo.end() ) {
1074 handleDetElement(top);
1075 handlePlacement(top.placement());
1076 for( const auto& c : top.children() ) {
1077 collect_det_elements(c.second);
1078 }
1079 }
1080 }
1081
1082
1083 void DetectorChecksum::analyzeDetector(DetElement top) {
1084 Detector& description = m_detDesc;
1085 if (!top.isValid()) {
1086 throw std::runtime_error("Attempt to call analyzeDetector with an invalid geometry!");
1087 }
1088 GeometryInfo& geo = *(m_dataPtr = new GeometryInfo);
1089 m_data->clear();
1090 handleHeader();
1091 collect_det_elements(top);
1092 for (const auto& fld : description.fields() )
1093 handleField(fld.second);
1094 if ( debug > 1 ) {
1095 printout(ALWAYS, "DetectorChecksum", "++ ==> Computing checksum for tree: %s", top.path().c_str());
1096 printout(ALWAYS, "DetectorChecksum", "++ Handled %ld materials.", geo.mapOfMaterials.size());
1097 printout(ALWAYS, "DetectorChecksum", "++ Handled %ld solids.", geo.mapOfSolids.size());
1098 printout(ALWAYS, "DetectorChecksum", "++ Handled %ld volumes.", geo.mapOfVolumes.size());
1099 printout(ALWAYS, "DetectorChecksum", "++ Handled %ld vis.attributes.", geo.mapOfVis.size());
1100 printout(ALWAYS, "DetectorChecksum", "++ Handled %ld fields.", geo.mapOfFields.size());
1101 }
1102 }
1103
1104 std::vector<PlacedVolume> _get_path(PlacedVolume node, const std::set<PlacedVolume>& match) {
1105 if ( match.end() == match.find(node) ) {
1106 const TObjArray* dau = node.volume()->GetNodes();
1107 for (Int_t i = 0, n_dau = dau->GetEntries(); i < n_dau; ++i) {
1108 TGeoNode* n = reinterpret_cast<TGeoNode*>(dau->At(i));
1109 auto cont = _get_path(n, match);
1110 if ( !cont.empty() ) {
1111 cont.emplace_back(node);
1112 return cont;
1113 }
1114 }
1115 return { };
1116 }
1117 return { node };
1118 }
1119
1120 void DetectorChecksum::hash_debug(const std::string& prefix, const entry_t& ent, int flg) const {
1121 if ( debug > 2 ) {
1122 if ( flg == 1 ) {
1123 debug_hash << std::setw(16) << std::left << prefix << "." << ent.data << std::endl;
1124 return;
1125 }
1126 debug_hash << std::setw(16) << std::left << (prefix+".hash64: ") << (void*)ent.hash << std::endl;
1127 if ( debug > 3 ) {
1128 debug_hash << std::setw(16) << std::left << prefix << ": |" << ent.data << "|" << std::endl;
1129 }
1130 }
1131 }
1132
1133 void DetectorChecksum::checksumDetElement(int lvl, DetElement det, hashes_t& hashes, bool recursive) const {
1134 auto& dat = data();
1135 auto& geo = dat.mapOfDetElements;
1136 auto it = geo.find(det);
1137 if ( it != geo.end() ) {
1138 std::set<PlacedVolume> child_places;
1139 std::set<PlacedVolume> hashed_places;
1140 auto det_pv = det.placement();
1141 std::size_t hash_idx_de = hashes.size();
1142
1143
1144 hashes.push_back(it->second.hash);
1145 hash_debug(det.name(), it->second);
1146 std::size_t hash_idx_ro = hashes.size();
1147 std::size_t hash_idx_id = 0;
1148 std::size_t hash_idx_seg = 0;
1149 if ( hash_readout ) {
1150 SensitiveDetector sd = m_detDesc.sensitiveDetector(det.name());
1151 if ( sd.isValid() ) {
1152 Readout ro = sd.readout();
1153 const auto& sens_ent = handleSensitive(sd);
1154 hashes.push_back(sens_ent.hash);
1155 hash_debug(" .sensitive", sens_ent);
1156 if ( ro.isValid() ) {
1157 const auto& id_ent = handleIdSpec(ro.idSpec());
1158 const auto& seg_ent = handleSegmentation(ro.segmentation());
1159
1160 hash_idx_id = hashes.size();
1161 hashes.push_back(id_ent.hash);
1162 hash_idx_seg = hashes.size();
1163 hashes.push_back(seg_ent.hash);
1164
1165 hash_debug(" .iddesc", id_ent);
1166 hash_debug(" .readout", seg_ent);
1167 }
1168 }
1169 }
1170
1171 std::size_t hash_idx_pv = hashes.size();
1172 checksumPlacement(det_pv, hashes, false);
1173 for ( const auto& c : det.children() )
1174 child_places.emplace(c.second.placement());
1175
1176
1177
1178
1179 std::size_t hash_idx_daughters = hashes.size();
1180 for( const auto& pv : child_places ) {
1181 auto chain = _get_path(pv, child_places);
1182 for( std::size_t i=0; i < chain.size()-1; ++i ) {
1183 checksumPlacement(chain[i], hashes, false);
1184 hashed_places.insert(chain[i]);
1185 }
1186 if ( !chain.empty() ) hashed_places.insert(chain[chain.size()-1]);
1187 }
1188
1189
1190 const TObjArray* dau = det_pv.volume()->GetNodes();
1191 if (dau && dau->GetEntries() > 0) {
1192 for (Int_t i = 0, n_dau = dau->GetEntries(); i < n_dau; ++i) {
1193 PlacedVolume pv = reinterpret_cast<TGeoNode*>(dau->At(i));
1194 if ( hashed_places.find(pv) == hashed_places.end() ) {
1195 checksumPlacement(det_pv, hashes, true);
1196 }
1197 }
1198 }
1199
1200
1201 std::size_t hash_idx_children = hashes.size();
1202 if ( recursive ) {
1203 for ( const auto& c : det.children() )
1204 checksumDetElement(lvl+1, c.second, hashes, recursive);
1205 }
1206
1207
1208 if ( debug > 0 || lvl <= max_level ) {
1209 std::stringstream str;
1210 hash_t code = detail::hash64(&hashes[hash_idx_de], (hash_idx_ro-hash_idx_de)*sizeof(hash_t));
1211 str << "+++ " << std::setw(4) << std::left << lvl
1212 << " " << std::setw(36) << std::left << det.name() << " de"
1213 << " " << std::setfill('0') << std::setw(16) << std::hex << code;
1214 code = detail::hash64(&hashes[hash_idx_pv], sizeof(hash_t));
1215 str << " " << std::setfill(' ') << std::setw(9) << std::left << "+place"
1216 << " " << std::setfill('0') << std::setw(16) << std::hex << code;
1217 code = detail::hash64(&hashes[hash_idx_daughters], (hash_idx_children-hash_idx_daughters)*sizeof(hash_t));
1218 if ( !(child_places.empty() && hashed_places.empty()) )
1219 str << " " << std::setfill(' ') << std::setw(10) << std::left << "+daughters"
1220 << " " << std::setfill('0') << std::setw(16) << std::hex << code;
1221 code = detail::hash64(&hashes[hash_idx_children], (hashes.size()-hash_idx_children)*sizeof(hash_t));
1222 if ( !det.children().empty() )
1223 str << " " << std::setfill(' ') << std::setw(9) << std::left << "+children"
1224 << " " << std::setfill('0') << std::setw(16) << std::hex << code;
1225 std::cout << str.str() << std::endl;
1226 if ( hash_idx_pv-hash_idx_ro > 0 ) {
1227 str.str("");
1228 str << std::setfill(' ') << "+++ " << std::setw(4) << std::left << lvl
1229 << " " << std::setw(56) << std::left << " ";
1230 code = detail::hash64(&hashes[hash_idx_ro], (hash_idx_pv-hash_idx_ro)*sizeof(hash_t));
1231 str << " " << std::setfill(' ') << std::setw(9) << std::left << "+readout"
1232 << " " << std::setfill('0') << std::setw(16) << std::hex << code;
1233 if ( hash_idx_id > 0 ) {
1234 code = detail::hash64(&hashes[hash_idx_id], sizeof(hash_t));
1235 str << " " << std::setfill(' ') << std::setw(10) << std::left << "+iddesc"
1236 << " " << std::setfill('0') << std::setw(16) << std::hex << code;
1237 }
1238 if ( hash_idx_seg > 0 ) {
1239 code = detail::hash64(&hashes[hash_idx_seg], sizeof(hash_t));
1240 str << " " << std::setfill(' ') << std::setw(9) << std::left << "+segment"
1241 << " " << std::setfill('0') << std::setw(16) << std::hex << code;
1242 }
1243 std::cout << str.str() << std::endl;
1244 }
1245 if ( lvl == 0 ) {
1246 str.str("");
1247 code = detail::hash64(&hashes[0], hashes.size()*sizeof(hash_t));
1248 str << std::setfill(' ') << "+++ " << std::setw(4) << std::left << lvl
1249 << " " << std::setw(39) << std::left << "Combined hash code"
1250 << " " << std::setfill('0') << std::setw(16) << std::hex << code
1251 << " (" << std::dec << hashes.size() << " sub-codes)";
1252 std::cout << str.str() << std::endl;
1253 }
1254 }
1255 return;
1256 }
1257 except("DetectorChecksum","ERROR: Cannot checksum invalid DetElement");
1258 }
1259
1260 void DetectorChecksum::checksumPlacement(PlacedVolume pv, hashes_t& hashes, bool recursive) const {
1261 handlePlacement(pv);
1262 auto& geo = data().mapOfPlacements;
1263 auto it = geo.find(pv);
1264 if ( it != geo.end() ) {
1265 Volume v = pv.volume();
1266 const auto& vol = handleVolume(v);
1267 entry_t name_entry {0, pv.name()};
1268
1269 hash_debug(" .place.name", name_entry, 1);
1270 hash_debug(" .place", it->second);
1271 hashes.push_back(it->second.hash);
1272 hashes.push_back(vol.hash);
1273 hash_debug(" .place.vol", vol);
1274 if ( !v.isAssembly() ) {
1275 const auto& mat = handleMaterial(v.material());
1276 hashes.push_back(mat.hash);
1277 hash_debug(" .place.mat", mat);
1278 }
1279 if ( recursive ) {
1280 const TObjArray* dau = v->GetNodes();
1281 if (dau && dau->GetEntries() > 0) {
1282 for (Int_t i = 0, n_dau = dau->GetEntries(); i < n_dau; ++i) {
1283 PlacedVolume node = reinterpret_cast<TGeoNode*>(dau->At(i));
1284 checksumPlacement(node, hashes, recursive);
1285 }
1286 }
1287 }
1288 return;
1289 }
1290 except("DetectorChecksum","ERROR: Cannot checksum invalid PlacedVolume");
1291 }
1292
1293
1294 void DetectorChecksum::dump_elements() const {
1295 _do_output_name("Element", reorder, write_files, debug>1 && have_hash_strings, data().mapOfElements);
1296 }
1297
1298
1299 void DetectorChecksum::dump_materials() const {
1300 _do_output_name("Material", reorder, write_files, debug>1 && have_hash_strings, data().mapOfMaterials);
1301 }
1302
1303
1304 void DetectorChecksum::dump_solids() const {
1305 _do_output_name("Solid", reorder, write_files, debug>1 && have_hash_strings, data().mapOfSolids);
1306 }
1307
1308
1309 void DetectorChecksum::dump_positions() const {
1310 _do_output("Position", reorder, write_files, have_hash_strings, data().mapOfPositions);
1311 }
1312
1313
1314 void DetectorChecksum::dump_rotations() const {
1315 _do_output("Rotation", reorder, write_files, have_hash_strings, data().mapOfRotations);
1316 }
1317
1318
1319 void DetectorChecksum::dump_volumes() const {
1320 _do_output_name("Volume", reorder, write_files, debug>1 && have_hash_strings, data().mapOfVolumes);
1321 }
1322
1323
1324 void DetectorChecksum::dump_placements() const {
1325 _do_output_name("Placement", reorder, write_files, debug>1 && have_hash_strings, data().mapOfPlacements);
1326 }
1327
1328
1329 void DetectorChecksum::dump_iddescriptors() const {
1330 _do_output_name("ID desc", reorder, write_files, debug>1 && have_hash_strings, data().mapOfIdSpecs);
1331 }
1332
1333
1334 void DetectorChecksum::dump_segmentations() const {
1335 _do_output_name("Segment", reorder, write_files, debug>1 && have_hash_strings, data().mapOfSegmentations);
1336 }
1337
1338
1339 void DetectorChecksum::dump_sensitives() const {
1340 _do_output_name("Sens.Det", reorder, write_files, debug>0 && have_hash_strings, data().mapOfSensDets);
1341 }
1342
1343
1344 void DetectorChecksum::dump_detelements() const {
1345 const auto& geo = data().mapOfDetElements;
1346 for(const auto& e : geo) {
1347 DetElement de = e.first;
1348 printout(ALWAYS, "DetectorChecksum", "+++ Detelement: 0x%016lx %-32s %s",
1349 e.second.hash, de.name(), debug > 2 ? ("\n"+e.second.data).c_str() : "");
1350 if ( de.path() == "/world" ) {
1351 PlacedVolume pv = de.placement();
1352 Volume vol = pv.volume();
1353 Solid sol = vol.solid();
1354 const auto& es = handleSolid(sol);
1355 const auto& ev = handleVolume(vol);
1356 const auto& ep = handlePlacement(pv);
1357
1358 printout(ALWAYS, "DetectorChecksum", " Solid: 0x%016lx %-32s %s",
1359 es.hash, sol.name(), debug > 2 ? ("\n"+es.data).c_str() : "");
1360 printout(ALWAYS, "DetectorChecksum", " Volume: 0x%016lx %-32s %s",
1361 ev.hash, vol.name(), debug > 2 ? ("\n"+ev.data).c_str() : "");
1362 printout(ALWAYS, "DetectorChecksum", " Placement: 0x%016lx %-32s %s",
1363 ep.hash, pv.name(), debug > 2 ? ("\n"+ep.data).c_str() : "");
1364 }
1365 }
1366 }
1367
1368 static long create_checksum(Detector& description, int argc, char** argv) {
1369 std::vector<std::string> detectors;
1370 int precision = 6, newline = 1, level = 1, meshes = 0, readout = 0, debug = 0;
1371 int dump_elements = 0, dump_materials = 0, dump_solids = 0, dump_volumes = 0;
1372 int dump_placements = 0, dump_detelements = 0, dump_sensitives = 0;
1373 int dump_iddesc = 0, dump_segmentations = 0, dump_pos = 0;
1374 int dump_rot = 0;
1375 int have_hash_strings = 0, reorder = 0, write_files = 0;
1376 std::string len_unit, ang_unit, ene_unit, dens_unit, atom_unit;
1377
1378 for(int i = 0; i < argc && argv[i]; ++i) {
1379 if ( 0 == ::strncmp("-detector",argv[i],4) && (i+1)<argc )
1380 detectors.emplace_back(argv[++i]);
1381 else if ( 0 == ::strncmp("-precision",argv[i],4) && (i+1)<argc )
1382 precision = ::atol(argv[++i]);
1383 else if ( 0 == ::strncmp("-length_unit",argv[i],10) && (i+1)<argc )
1384 len_unit = argv[++i];
1385 else if ( 0 == ::strncmp("-angle_unit",argv[i],10) && (i+1)<argc )
1386 ang_unit = argv[++i];
1387 else if ( 0 == ::strncmp("-energy_unit",argv[i],10) && (i+1)<argc )
1388 ene_unit = argv[++i];
1389 else if ( 0 == ::strncmp("-density_unit",argv[i],10) && (i+1)<argc )
1390 dens_unit = argv[++i];
1391 else if ( 0 == ::strncmp("-atomic_unit",argv[i],10) && (i+1)<argc )
1392 atom_unit = argv[++i];
1393 else if ( 0 == ::strncmp("-level", argv[i],5) && (i+1)<argc )
1394 level = ::atol(argv[++i]);
1395 else if ( 0 == ::strncmp("-debug", argv[i],5) && (i+1)<argc )
1396 debug = ::atol(argv[++i]);
1397 else if ( 0 == ::strncmp("+newline",argv[i],5) )
1398 newline = 0;
1399 else if ( 0 == ::strncmp("-meshes",argv[i],5) )
1400 meshes = 1;
1401 else if ( 0 == ::strncmp("-readout",argv[i],5) )
1402 readout = 1;
1403 else if ( 0 == ::strncmp("-dump_elements",argv[i],10) )
1404 dump_elements = 1;
1405 else if ( 0 == ::strncmp("-dump_materials",argv[i],10) )
1406 dump_materials = 1;
1407 else if ( 0 == ::strncmp("-dump_solids",argv[i],10) )
1408 dump_solids = 1;
1409 else if ( 0 == ::strncmp("-dump_volumes",argv[i],10) )
1410 dump_volumes = 1;
1411 else if ( 0 == ::strncmp("-dump_positions",argv[i],12) )
1412 dump_pos = 1;
1413 else if ( 0 == ::strncmp("-dump_rotations",argv[i],12) )
1414 dump_rot = 1;
1415 else if ( 0 == ::strncmp("-dump_placements",argv[i],10) )
1416 dump_placements = 1;
1417 else if ( 0 == ::strncmp("-dump_detelements",argv[i],10) )
1418 dump_detelements = 1;
1419 else if ( 0 == ::strncmp("-dump_sensitives",argv[i],10) )
1420 dump_sensitives = 1;
1421 else if ( 0 == ::strncmp("-dump_segmentations",argv[i],10) )
1422 dump_segmentations = 1;
1423 else if ( 0 == ::strncmp("-dump_iddescriptors",argv[i],10) )
1424 dump_iddesc = 1;
1425 else if ( 0 == ::strncmp("-write_files",argv[i],8) )
1426 write_files = 1;
1427 else if ( 0 == ::strncmp("-reorder",argv[i],6) )
1428 reorder = 1;
1429 else if ( 0 == ::strncmp("-keep_hashes",argv[i],8) )
1430 have_hash_strings = 1;
1431 else {
1432 std::cout <<
1433 "Usage: -plugin DD4hepDetectorChecksum -arg [-arg] \n\n"
1434 " -detector <string> Top level DetElement path. Default: '/world' \n"
1435 " -meshes also hash the detector's meshed solids \n"
1436 " (may be sensitive to changes due to rounding) \n"
1437 " default: false \n"
1438 " -readout also hash the detector's readout properties \n"
1439 " (sensitive det, id desc, segmentation) \n"
1440 " default: false \n"
1441 " -keep_hash keep the hash strings (not only hash codes. \n"
1442 " Useful for debugging and -dump_<x> options. \n"
1443 " -precsision <digits> Set floating point precision after comma \n"
1444 " for the checsum calculation. \n"
1445 " \n"
1446 " Debugging: Dump individual hash codes (debug>=1) \n"
1447 " Debugging: and the hashed string (debug>2) \n"
1448 " -dump_elements Dump hashes of used elements \n"
1449 " -dump_materials Dump hashes of used materials \n"
1450 " -dump_solids Dump hashes of used solids \n"
1451 " -dump_volumes Dump hashes of used volumes \n"
1452 " -dump_positions Dump hashes of used positions \n"
1453 " -dump_rotations Dump hashes of used rotations \n"
1454 " -dump_placements Dump hashes of used placements \n"
1455 " -dump_detelements Dump hashes of used detelements \n"
1456 " -dump_sensitive Dump hashes of sensitive detectors \n"
1457 " -dump_iddescriptors Dump hashes of ID descriptors \n"
1458 " -dump_segmentations Dump hashes of readout segmentations \n"
1459 " -write_files Write a file for each category dumped (debugging). \n"
1460 " File name is <item>.txt (aka. Positions.txt etc. \n"
1461 " -reorder Reorder dump containers according to hash. \n"
1462 " \n"
1463 " Modify units in the created hash strings (deprecated): \n"
1464 " -length_unit <value> Unit of length as literal. default: mm \n"
1465 " -angle_unit <value> Unit of angle as literal. default: deg \n"
1466 " -energy_unit <value> Unit of energy as literal. default: GeV \n"
1467 " -density_unit <value> Unit of density as literal. default: g/cm3 \n"
1468 " -atomic_unit <value> Unit of atomic weight as literal. default: g/mole \n"
1469 " \n"
1470 " -debug <number> Steer additional debug printouts (gets verbose) \n"
1471 " -help Print this help output \n\n"
1472 " Arguments given: " << arguments(argc, argv) << std::endl << std::flush;
1473 ::exit(EINVAL);
1474 }
1475 }
1476 DetectorChecksum wr(description);
1477 DetElement de = description.world();
1478 wr.precision = precision;
1479 if ( !len_unit.empty() ) wr.m_len_unit_nam = std::move(len_unit);
1480 if ( !ang_unit.empty() ) wr.m_ang_unit_nam = std::move(ang_unit);
1481 if ( !ene_unit.empty() ) wr.m_ene_unit_nam = std::move(ene_unit);
1482 if ( !dens_unit.empty() ) wr.m_densunit_nam = std::move(dens_unit);
1483 if ( !atom_unit.empty() ) wr.m_atomunit_nam = std::move(atom_unit);
1484 if ( newline ) wr.newline = "\n";
1485 wr.have_hash_strings = have_hash_strings;
1486 wr.write_files = write_files;
1487 wr.reorder = reorder;
1488 wr.hash_meshes = meshes;
1489 wr.hash_readout = readout;
1490 wr.max_level = level;
1491 wr.debug = debug;
1492 wr.configure();
1493
1494 bool make_dump = false;
1495 if ( dump_elements || dump_materials || dump_solids ||
1496 dump_volumes || dump_placements || dump_detelements ||
1497 dump_sensitives || dump_iddesc || dump_segmentations ||
1498 dump_pos || dump_rot )
1499 {
1500 make_dump = true;
1501 wr.debug = 1;
1502 }
1503 int round = std::fegetround();
1504 std::fesetround(FE_TONEAREST);
1505 printout(INFO,"DetectorChecksum","+++ Rounding mode: %d new: %d", round, std::fegetround());
1506
1507 DetectorChecksum::hashes_t hash_vec;
1508 DetectorChecksum::hash_t checksum = 0;
1509 if ( !detectors.empty() ) {
1510 for (const auto& det : detectors ) {
1511 de = detail::tools::findElement(description,det);
1512 wr.analyzeDetector(de);
1513 hash_vec.clear();
1514 wr.checksumDetElement(0, de, hash_vec, true);
1515 if ( wr.debug > 2 ) {
1516 std::cout << wr.debug_hash.str() << std::endl;
1517 wr.debug_hash.str("");
1518 }
1519 checksum = detail::hash64(&hash_vec[0], hash_vec.size()*sizeof(DetectorChecksum::hash_t));
1520 printout(ALWAYS,"DetectorChecksum","+++ Checksum for %s 0x%016lx",
1521 de.path().c_str(), checksum);
1522 if ( make_dump ) goto MakeDump;
1523 }
1524 return 1;
1525 }
1526
1527
1528 wr.analyzeDetector(de);
1529 hash_vec.push_back(wr.handleHeader().hash);
1530 wr.checksumDetElement(0, description.world(), hash_vec, true);
1531 checksum = detail::hash64(&hash_vec[0], hash_vec.size()*sizeof(DetectorChecksum::hash_t));
1532 if ( wr.debug > 2 ) std::cout << wr.debug_hash.str() << std::endl;
1533 printout(ALWAYS,"DetectorChecksum","+++ Checksum for %s 0x%016lx",
1534 de.path().c_str(), checksum);
1535
1536 MakeDump:
1537 if ( make_dump ) {
1538 wr.debug = debug;
1539 if ( dump_elements ) wr.dump_elements();
1540 if ( dump_materials ) wr.dump_materials();
1541 if ( dump_pos ) wr.dump_positions();
1542 if ( dump_rot ) wr.dump_rotations();
1543 if ( dump_solids ) wr.dump_solids();
1544 if ( dump_volumes ) wr.dump_volumes();
1545 if ( dump_placements ) wr.dump_placements();
1546 if ( dump_sensitives ) wr.dump_sensitives();
1547 if ( dump_segmentations ) wr.dump_segmentations();
1548 if ( dump_iddesc ) wr.dump_iddescriptors();
1549 if ( dump_detelements ) wr.dump_detelements();
1550 }
1551 return 1;
1552 }
1553
1554 DECLARE_APPLY(DD4hepDetectorChecksum, create_checksum)