File indexing completed on 2026-10-05 08:16:12
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021 #include <DD4hep/DetFactoryHelper.h>
0022 #include <DD4hep/DetectorTools.h>
0023 #include <DD4hep/MatrixHelpers.h>
0024 #include <DD4hep/PropertyTable.h>
0025 #include <DD4hep/OpticalSurfaces.h>
0026 #include <DD4hep/OpticalSurfaceManager.h>
0027 #include <DD4hep/IDDescriptor.h>
0028 #include <DD4hep/DD4hepUnits.h>
0029 #include <DD4hep/FieldTypes.h>
0030 #include <DD4hep/Printout.h>
0031 #include <DD4hep/Factories.h>
0032 #include <DD4hep/Path.h>
0033 #include <DD4hep/Plugins.h>
0034 #include <DD4hep/detail/SegmentationsInterna.h>
0035 #include <DD4hep/detail/DetectorInterna.h>
0036 #include <DD4hep/detail/ObjectsInterna.h>
0037
0038 #include <XML/DocumentHandler.h>
0039 #include <XML/Utilities.h>
0040
0041
0042 #include <TGeoManager.h>
0043 #include <TGeoMaterial.h>
0044 #include <TGeoPhysicalConstants.h>
0045 #include <TGDMLMatrix.h>
0046 #include <TMath.h>
0047
0048
0049 #include <filesystem>
0050 #include <iostream>
0051 #include <climits>
0052 #include <set>
0053
0054 using namespace dd4hep;
0055
0056
0057 namespace dd4hep {
0058
0059 class Debug;
0060 class World;
0061 class Isotope;
0062 class Plugin;
0063 class Compact;
0064 class Includes;
0065 class IncludeFile;
0066 class Property;
0067 class XMLFile;
0068 class JsonFile;
0069 class PropertyConstant;
0070 class Parallelworld_Volume;
0071 class DetElementInclude;
0072 class STD_Conditions;
0073
0074
0075 template <> void Converter<Debug>::operator()(xml_h element) const;
0076 template <> void Converter<World>::operator()(xml_h element) const;
0077 template <> void Converter<Plugin>::operator()(xml_h element) const;
0078 template <> void Converter<Constant>::operator()(xml_h element) const;
0079 template <> void Converter<Material>::operator()(xml_h element) const;
0080 template <> void Converter<Atom>::operator()(xml_h element) const;
0081 template <> void Converter<Isotope>::operator()(xml_h element) const;
0082 template <> void Converter<VisAttr>::operator()(xml_h element) const;
0083 template <> void Converter<Region>::operator()(xml_h element) const;
0084 template <> void Converter<Readout>::operator()(xml_h element) const;
0085 template <> void Converter<Segmentation>::operator()(xml_h element) const;
0086 template <> void Converter<LimitSet>::operator()(xml_h element) const;
0087 template <> void Converter<Property>::operator()(xml_h element) const;
0088 template <> void Converter<CartesianField>::operator()(xml_h element) const;
0089 template <> void Converter<SensitiveDetector>::operator()(xml_h element) const;
0090 template <> void Converter<OpticalSurface>::operator()(xml_h element) const;
0091 template <> void Converter<PropertyTable>::operator()(xml_h element) const;
0092 template <> void Converter<PropertyConstant>::operator()(xml_h element) const;
0093 template <> void Converter<DetElement>::operator()(xml_h element) const;
0094 template <> void Converter<STD_Conditions>::operator()(xml_h element) const;
0095 template <> void Converter<IncludeFile>::operator()(xml_h element) const;
0096 template <> void Converter<JsonFile>::operator()(xml_h element) const;
0097 template <> void Converter<XMLFile>::operator()(xml_h element) const;
0098 template <> void Converter<Header>::operator()(xml_h element) const;
0099 template <> void Converter<DetElementInclude>::operator()(xml_h element) const;
0100 template <> void Converter<Parallelworld_Volume>::operator()(xml_h element) const;
0101 template <> void Converter<Compact>::operator()(xml_h element) const;
0102 }
0103
0104 namespace {
0105 static UInt_t unique_mat_id = 0xAFFEFEED;
0106 void throw_print(const std::string& msg) {
0107 printout(ERROR, "Compact", msg.c_str());
0108 throw std::runtime_error(msg);
0109 }
0110 class DebugOptions {
0111 public:
0112 bool readout = false;
0113 bool regions = false;
0114 bool limits = false;
0115 bool visattr = false;
0116 bool isotopes = false;
0117 bool elements = false;
0118 bool materials = false;
0119 bool segmentation = false;
0120 bool constants = false;
0121 bool includes = false;
0122 bool matrix = false;
0123 bool surface = false;
0124 bool detelements = false;
0125 bool include_guard= true;
0126 } s_debug;
0127 }
0128
0129 static Ref_t create_ConstantField(Detector& description, xml_h e) {
0130 CartesianField obj;
0131 xml_comp_t field(e), strength(e.child(_U(strength)));
0132 xml_dim_t solid = field.child(_U(shape), false);
0133 std::string type = e.attr<std::string>(_U(field));
0134 ConstantField* ptr = new ConstantField();
0135
0136 ptr->field_type = ::toupper(type[0]) == 'E' ? CartesianField::ELECTRIC : CartesianField::MAGNETIC;
0137 ptr->direction.SetX(strength.x());
0138 ptr->direction.SetY(strength.y());
0139 ptr->direction.SetZ(strength.z());
0140 ptr->flag = 0;
0141 if ( solid ) {
0142 std::string solid_type = solid.typeStr();
0143 xml_dim_t _pos = solid.child(_U(position), false);
0144 xml_dim_t _rot = solid.child(_U(rotation), false);
0145 RotationZYX rot;
0146 Position pos;
0147 ptr->volume = xml::createShape(description, solid_type, solid);
0148 ptr->flag |= ConstantField::FIELD_LOCAL;
0149 if( _pos ) {
0150 ptr->flag |= ConstantField::FIELD_TRANSLATED;
0151 pos.SetXYZ(_pos.x(), _pos.y(), _pos.z());
0152 }
0153 if( _rot ) {
0154 ptr->flag |= ConstantField::FIELD_ROTATED;
0155 rot.SetComponents(_rot.z(), _rot.y(), _rot.x());
0156 }
0157 auto tr = Transform3D(rot, pos);
0158 ptr->inverse_pos = tr.Inverse();
0159 }
0160 obj.assign(ptr, field.nameStr(), field.typeStr());
0161 return obj;
0162 }
0163 DECLARE_XMLELEMENT(ConstantField,create_ConstantField)
0164
0165 static Ref_t create_SolenoidField(Detector& description, xml_h e) {
0166 xml_comp_t c(e);
0167 bool has_inner_radius = c.hasAttr(_U(inner_radius));
0168 bool has_outer_radius = c.hasAttr(_U(outer_radius));
0169
0170 if (!has_inner_radius && !has_outer_radius) {
0171 throw_print("Compact2Objects[ERROR]: For a solenoidal field at least one of the "
0172 " xml attributes inner_radius of outer_radius MUST be set.");
0173 }
0174 CartesianField obj;
0175 SolenoidField* ptr = new SolenoidField();
0176
0177
0178
0179
0180
0181 if (has_inner_radius && has_outer_radius) {
0182 ptr->innerRadius = c.attr<double>(_U(inner_radius));
0183 ptr->outerRadius = c.attr<double>(_U(outer_radius));
0184 }
0185 else if (has_inner_radius) {
0186 Box box = description.worldVolume().solid();
0187 ptr->innerRadius = c.attr<double>(_U(inner_radius));
0188 ptr->outerRadius = box.x();
0189 }
0190 else if (has_outer_radius) {
0191 Box box = description.worldVolume().solid();
0192 ptr->innerRadius = c.attr<double>(_U(outer_radius));
0193 ptr->outerRadius = box.x();
0194 }
0195 if (c.hasAttr(_U(inner_field)))
0196 ptr->innerField = c.attr<double>(_U(inner_field));
0197 if (c.hasAttr(_U(outer_field)))
0198 ptr->outerField = c.attr<double>(_U(outer_field));
0199 if (c.hasAttr(_U(zmax)))
0200 ptr->maxZ = c.attr<double>(_U(zmax));
0201 else
0202 ptr->maxZ = description.constant<double>("world_side");
0203 if (c.hasAttr(_U(zmin)))
0204 ptr->minZ = c.attr<double>(_U(zmin));
0205 else
0206 ptr->minZ = -ptr->maxZ;
0207 ptr->field_type = CartesianField::MAGNETIC;
0208 obj.assign(ptr, c.nameStr(), c.typeStr());
0209 return obj;
0210 }
0211 DECLARE_XMLELEMENT(SolenoidMagnet,create_SolenoidField)
0212
0213 DECLARE_XMLELEMENT(solenoid,create_SolenoidField)
0214
0215 static Ref_t create_DipoleField(Detector& , xml_h e) {
0216 xml_comp_t c(e);
0217 CartesianField obj;
0218 DipoleField* ptr = new DipoleField();
0219 double lunit = c.hasAttr(_U(lunit)) ? c.attr<double>(_U(lunit)) : 1.0;
0220 double funit = c.hasAttr(_U(funit)) ? c.attr<double>(_U(funit)) : 1.0;
0221 double val, mult = funit;
0222
0223 if (c.hasAttr(_U(zmin)))
0224 ptr->zmin = _multiply<double>(c.attr<std::string>(_U(zmin)), lunit);
0225 if (c.hasAttr(_U(zmax)))
0226 ptr->zmax = _multiply<double>(c.attr<std::string>(_U(zmax)), lunit);
0227 if (c.hasAttr(_U(rmax)))
0228 ptr->rmax = _multiply<double>(c.attr<std::string>(_U(rmax)), lunit);
0229 for (xml_coll_t coll(c, _U(dipole_coeff)); coll; ++coll, mult /= lunit) {
0230 xml_dim_t coeff = coll;
0231 if ( coeff.hasAttr(_U(value)) )
0232 val = coll.attr<double>(_U(value)) * mult;
0233 else if ( coeff.hasAttr(_U(coefficient)) )
0234 val = coeff.coefficient() * mult;
0235 else
0236 val = _multiply<double>(coll.text(), mult);
0237 ptr->coefficents.emplace_back(val);
0238 }
0239 ptr->field_type = CartesianField::MAGNETIC;
0240 obj.assign(ptr, c.nameStr(), c.typeStr());
0241 return obj;
0242 }
0243 DECLARE_XMLELEMENT(DipoleMagnet,create_DipoleField)
0244
0245 static Ref_t create_MultipoleField(Detector& description, xml_h e) {
0246 xml_dim_t c(e), child;
0247 CartesianField obj;
0248 MultipoleField* ptr = new MultipoleField();
0249 double lunit = c.hasAttr(_U(lunit)) ? c.attr<double>(_U(lunit)) : 1.0;
0250 double funit = c.hasAttr(_U(funit)) ? c.attr<double>(_U(funit)) : 1.0;
0251 double val, mult = funit, bz = 0.0;
0252 RotationZYX rot;
0253 Position pos;
0254
0255 if (c.hasAttr(_U(Z))) bz = c.Z() * funit;
0256 if ((child = c.child(_U(position), false))) {
0257 pos.SetXYZ(child.x(), child.y(), child.z());
0258 }
0259 if ((child = c.child(_U(rotation), false))) {
0260 rot.SetComponents(child.z(), child.y(), child.x());
0261 }
0262 if ((child = c.child(_U(shape), false))) {
0263 std::string type = child.typeStr();
0264 ptr->volume = xml::createShape(description, type, child);
0265 }
0266 ptr->B_z = bz;
0267 ptr->transform = Transform3D(rot,pos);
0268 for (xml_coll_t coll(c, _U(coefficient)); coll; ++coll, mult /= lunit) {
0269 xml_dim_t coeff = coll;
0270 if ( coll.hasAttr(_U(value)) )
0271 val = coll.attr<double>(_U(value)) * mult;
0272 else
0273 val = coeff.coefficient(0.0) * mult;
0274 ptr->coefficents.emplace_back(val);
0275 val = coeff.skew(0.0) * mult;
0276 ptr->skews.emplace_back(val);
0277 }
0278 ptr->field_type = CartesianField::MAGNETIC;
0279 obj.assign(ptr, c.nameStr(), c.typeStr());
0280 return obj;
0281 }
0282 DECLARE_XMLELEMENT(MultipoleMagnet,create_MultipoleField)
0283
0284 static long load_Compact(Detector& description, xml_h element) {
0285 Converter<Compact>converter(description);
0286 converter(element);
0287 return 1;
0288 }
0289 DECLARE_XML_DOC_READER(lccdd,load_Compact)
0290 DECLARE_XML_DOC_READER(compact,load_Compact)
0291
0292
0293
0294 class ProcessedFilesSet: public std::set<std::string> {};
0295
0296
0297 bool check_process_file(Detector& description, std::string filename) {
0298
0299
0300
0301 auto already_processed = description.extension<ProcessedFilesSet>( false );
0302 if ( !already_processed ) {
0303 already_processed = new ProcessedFilesSet( );
0304 description.addExtension<ProcessedFilesSet>(already_processed );
0305 }
0306 std::string npath = dd4hep::Path{filename}.normalize();
0307 if (already_processed->find(npath) != already_processed->end() ) {
0308 printout(INFO, "Compact","++ Already processed xml document %s.", npath.c_str());
0309 return true;
0310 }
0311 already_processed->insert(npath);
0312 return false;
0313 }
0314
0315
0316
0317 template <> void Converter<Debug>::operator()(xml_h e) const {
0318 for (xml_coll_t coll(e, _U(type)); coll; ++coll) {
0319 int val = coll.attr<int>(_U(value));
0320 std::string nam = coll.attr<std::string>(_U(name));
0321 if ( nam.substr(0,6) == "isotop" ) s_debug.isotopes = (0 != val);
0322 else if ( nam.substr(0,6) == "elemen" ) s_debug.elements = (0 != val);
0323 else if ( nam.substr(0,6) == "materi" ) s_debug.materials = (0 != val);
0324 else if ( nam.substr(0,6) == "visatt" ) s_debug.visattr = (0 != val);
0325 else if ( nam.substr(0,6) == "region" ) s_debug.regions = (0 != val);
0326 else if ( nam.substr(0,6) == "readou" ) s_debug.readout = (0 != val);
0327 else if ( nam.substr(0,6) == "limits" ) s_debug.limits = (0 != val);
0328 else if ( nam.substr(0,6) == "segmen" ) s_debug.segmentation = (0 != val);
0329 else if ( nam.substr(0,6) == "consta" ) s_debug.constants = (0 != val);
0330 else if ( nam.substr(0,6) == "define" ) s_debug.constants = (0 != val);
0331 else if ( nam.substr(0,6) == "includ" ) s_debug.includes = (0 != val);
0332 else if ( nam.substr(0,6) == "matrix" ) s_debug.matrix = (0 != val);
0333 else if ( nam.substr(0,6) == "surfac" ) s_debug.surface = (0 != val);
0334 else if ( nam.substr(0,6) == "incgua" ) s_debug.include_guard= (0 != val);
0335 else if ( nam.substr(0,6) == "detele" ) s_debug.detelements = (0 != val);
0336 }
0337 }
0338
0339
0340
0341
0342
0343 template <> void Converter<Plugin>::operator()(xml_h e) const {
0344 xml_comp_t plugin(e);
0345 std::string name = plugin.nameStr();
0346 std::string type = "default";
0347
0348 if ( xml_attr_t typ_attr = e.attr_nothrow(_U(type)) ) {
0349 type = e.attr<std::string>(typ_attr);
0350 }
0351 if ( type == "default" ) {
0352 std::vector<char*> argv;
0353 std::vector<std::string> arguments;
0354 for (xml_coll_t coll(e, _U(arg)); coll; ++coll) {
0355 std::string val = coll.attr<std::string>(_U(value));
0356 arguments.emplace_back(val);
0357 }
0358 for (xml_coll_t coll(e, _U(argument)); coll; ++coll) {
0359 std::string val = coll.attr<std::string>(_U(value));
0360 arguments.emplace_back(val);
0361 }
0362 for(std::vector<std::string>::iterator i=arguments.begin(); i!=arguments.end(); ++i)
0363 argv.emplace_back(&((*i)[0]));
0364 description.apply(name.c_str(),int(argv.size()), argv.empty() ? nullptr : &argv[0]);
0365 return;
0366 }
0367
0368 long result = PluginService::Create<long>(name, &description, &e);
0369 if (0 == result) {
0370 PluginDebug dbg;
0371 result = PluginService::Create<long>(name, &description, &e);
0372 if ( 0 == result ) {
0373 except("Compact","++ Failed to locate plugin %s - no factory: %s",
0374 name.c_str(), dbg.missingFactory(name).c_str());
0375 }
0376 }
0377 result = *(long*) result;
0378 if (result != 1) {
0379 except("Compact","++ Failed to execute plugin %s", name.c_str());
0380 }
0381 }
0382
0383
0384
0385
0386
0387 template <> void Converter<Constant>::operator()(xml_h e) const {
0388 if ( e.tag() != "include" ) {
0389 xml_ref_t constant(e);
0390 std::string nam = constant.attr<std::string>(_U(name));
0391 std::string val = constant.attr<std::string>(_U(value));
0392 std::string typ = constant.hasAttr(_U(type)) ? constant.attr<std::string>(_U(type)) : "number";
0393 Constant c(nam, val, typ);
0394 _toDictionary(nam, val, typ);
0395 description.addConstant(c);
0396 if ( s_debug.constants ) {
0397 printout(ALWAYS, "Compact",
0398 "++ Converting constant %-16s = %-32s [%s]", nam.c_str(), val.c_str(), typ.c_str());
0399 }
0400 return;
0401 }
0402 xml::DocumentHolder doc(xml::DocumentHandler().load(e, e.attr_value(_U(ref))));
0403 if ( s_debug.includes ) {
0404 printout(ALWAYS, "Compact","++ Processing xml document %s.",doc.uri().c_str());
0405 }
0406 xml_h root = doc.root();
0407 xml_coll_t(root, _U(define)).for_each(_U(constant), Converter<Constant>(description));
0408 xml_coll_t(root, _U(constant)).for_each(Converter<Constant>(description));
0409 }
0410
0411
0412
0413
0414
0415 template <> void Converter<Header>::operator()(xml_h e) const {
0416 xml_comp_t c(e);
0417 Header h = description.header();
0418 if( !h.isValid() ) {
0419 h = Header(e.attr<std::string>(_U(name)), e.attr<std::string>(_U(title), "Undefined"));
0420 h.setUrl(e.attr<std::string>(_U(url), "Undefined"));
0421 h.setAuthor(e.attr<std::string>(_U(author), "Undefined"));
0422 h.setStatus(e.attr<std::string>(_U(status), "development"));
0423 h.setVersion(e.attr<std::string>(_U(version), "Undefined"));
0424 h.setComment(e.hasChild(_U(comment)) ? e.child(_U(comment)).text() : "No Comment");
0425 description.setHeader(h);
0426 return;
0427 }
0428 printout(INFO, "Compact", "++ Overwriting/updating Header structure is dangerous. Try to avoid this.");
0429 printout(INFO, "Compact", "++ Header definition in: %s", xml::DocumentHandler::system_path(e).c_str());
0430 if( e.hasAttr(_U(comment)) ) h.setComment(e.attr<std::string>(_U(comment)).c_str());
0431 if( e.hasAttr(_U(version)) ) h.setVersion(e.attr<std::string>(_U(version)).c_str());
0432 if( e.hasAttr(_U(author)) ) h.setAuthor(e.attr<std::string>(_U(author)).c_str());
0433 if( e.hasAttr(_U(status)) ) h.setStatus(e.attr<std::string>(_U(status)).c_str());
0434 if( e.hasAttr(_U(title)) ) h.setTitle(e.attr<std::string>(_U(title)).c_str());
0435 if( e.hasAttr(_U(name)) ) h.setName(e.attr<std::string>(_U(name)).c_str());
0436 if( e.hasAttr(_U(url)) ) h.setUrl(e.attr<std::string>(_U(url)).c_str());
0437 }
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455 template <> void Converter<Material>::operator()(xml_h e) const {
0456 xml_ref_t x_mat(e);
0457 TGeoManager& mgr = description.manager();
0458 xml_tag_t mname = x_mat.name();
0459 const char* matname = mname.c_str();
0460 TGeoElementTable* table = mgr.GetElementTable();
0461 TGeoMaterial* mat = mgr.GetMaterial(matname);
0462 TGeoMixture* mix = dynamic_cast<TGeoMixture*>(mat);
0463 xml_coll_t fractions (x_mat, _U(fraction));
0464 xml_coll_t composites(x_mat, _U(composite));
0465
0466 if (0 == mat) {
0467 TGeoMaterial* comp_mat;
0468 TGeoElement* comp_elt;
0469 xml_h density = x_mat.child(_U(D), false);
0470 double dens_val = density.ptr() ? density.attr<double>(_U(value)) : 0.0;
0471 double dens_unit = 1.0;
0472
0473 if ( !density.ptr() ) {
0474 throw_print("Compact2Objects[ERROR]: material without density tag ( <D unit=\"g/cm3\" value=\"..\"/> ) provided: "
0475 + std::string( matname ) ) ;
0476 }
0477 if ( density.hasAttr(_U(unit)) ) {
0478 dens_unit = density.attr<double>(_U(unit))/xml::_toDouble(_Unicode(gram/cm3));
0479 }
0480 if ( dens_unit != 1.0 ) {
0481 dens_val *= dens_unit;
0482 printout(s_debug.materials ? ALWAYS : DEBUG, "Compact","Density unit: %.3f [%s] raw: %.3f normalized: %.3f ",
0483 dens_unit, density.attr<std::string>(_U(unit)).c_str(), dens_val, (dens_val*dens_unit));
0484 }
0485 mat = mix = new TGeoMixture(matname, composites.size(), dens_val);
0486 std::size_t ifrac = 0;
0487 std::vector<double> composite_fractions;
0488 double composite_fractions_total = 0.0;
0489 for (composites.reset(); composites; ++composites) {
0490 std::string nam = composites.attr<std::string>(_U(ref));
0491 double fraction = composites.attr<double>(_U(n));
0492 if (0 != (comp_mat = mgr.GetMaterial(nam.c_str())))
0493 fraction *= comp_mat->GetA();
0494 else if (0 != (comp_elt = table->FindElement(nam.c_str())))
0495 fraction *= comp_elt->A();
0496 else
0497 except("Compact2Objects","Converting material: %s Element missing: %s",mname.c_str(),nam.c_str());
0498 composite_fractions_total += fraction;
0499 composite_fractions.emplace_back(fraction);
0500 }
0501 for (composites.reset(), ifrac=0; composites; ++composites, ++ifrac) {
0502 std::string nam = composites.attr<std::string>(_U(ref));
0503 double fraction = composite_fractions[ifrac]/composite_fractions_total;
0504 if (0 != (comp_mat = mgr.GetMaterial(nam.c_str())))
0505 mix->AddElement(comp_mat, fraction);
0506 else if (0 != (comp_elt = table->FindElement(nam.c_str())))
0507 mix->AddElement(comp_elt, fraction);
0508 }
0509 for (fractions.reset(); fractions; ++fractions) {
0510 std::string nam = fractions.attr<std::string>(_U(ref));
0511 double fraction = fractions.attr<double>(_U(n));
0512 if (0 != (comp_mat = mgr.GetMaterial(nam.c_str())))
0513 mix->AddElement(comp_mat, fraction);
0514 else if (0 != (comp_elt = table->FindElement(nam.c_str())))
0515 mix->AddElement(comp_elt, fraction);
0516 else
0517 throw_print("Compact2Objects[ERROR]: Converting material:" + mname + " Element missing: " + nam);
0518 }
0519 xml_h temperature = x_mat.child(_U(T), false);
0520 double temp_val = description.stdConditions().temperature;
0521 if ( temperature.ptr() ) {
0522 double temp_unit = _toDouble("kelvin");
0523 if ( temperature.hasAttr(_U(unit)) )
0524 temp_unit = temperature.attr<double>(_U(unit));
0525 temp_val = temperature.attr<double>(_U(value)) * temp_unit;
0526 }
0527 xml_h pressure = x_mat.child(_U(P), false);
0528 double pressure_val = description.stdConditions().pressure;
0529 if ( pressure.ptr() ) {
0530 double pressure_unit = _toDouble("pascal");
0531 if ( pressure.hasAttr(_U(unit)) )
0532 pressure_unit = pressure.attr<double>(_U(unit));
0533 pressure_val = pressure.attr<double>(_U(value)) * pressure_unit;
0534 }
0535 #if 0
0536 printout(s_debug.materials ? ALWAYS : DEBUG, "Compact",
0537 "++ ROOT raw temperature and pressure: %.3g %.3g",
0538 mat->GetTemperature(),mat->GetPressure());
0539 #endif
0540 mat->SetTemperature(temp_val);
0541 mat->SetPressure(pressure_val);
0542 printout(s_debug.materials ? ALWAYS : DEBUG, "Compact",
0543 "++ Converting material %-16s Density: %9.7g Temperature:%9.7g [K] Pressure:%9.7g [hPa].",
0544 matname, dens_val, temp_val/dd4hep::kelvin, pressure_val/dd4hep::pascal/100.0);
0545
0546 mix->SetRadLen(0e0);
0547 mix->ComputeDerivedQuantities();
0548
0549
0550 for(xml_coll_t properties(x_mat, _U(constant)); properties; ++properties) {
0551 xml_elt_t p = properties;
0552 if ( p.hasAttr(_U(ref)) ) {
0553 bool err = kFALSE;
0554 std::string ref = p.attr<std::string>(_U(ref));
0555 mgr.GetProperty(ref.c_str(), &err);
0556 if ( err == kFALSE ) {
0557 std::string prop_nam = p.attr<std::string>(_U(name));
0558 mat->AddConstProperty(prop_nam.c_str(), ref.c_str());
0559 printout(s_debug.materials ? ALWAYS : DEBUG, "Compact",
0560 "++ material %-16s add constant property: %s -> %s.",
0561 mat->GetName(), prop_nam.c_str(), ref.c_str());
0562 continue;
0563 }
0564
0565 throw_print("Compact2Objects[ERROR]: Converting material:" + mname + " ConstProperty missing in TGeoManager: " + ref);
0566 }
0567 else if ( p.hasAttr(_U(value)) ) {
0568 std::stringstream str;
0569 std::string ref, prop_nam = p.attr<std::string>(_U(name));
0570 str << prop_nam << "_" << (void*)mat;
0571 ref = str.str();
0572 mgr.AddProperty(ref.c_str(), p.attr<double>(_U(value)));
0573 mat->AddConstProperty(prop_nam.c_str(), ref.c_str());
0574 printout(s_debug.materials ? ALWAYS : DEBUG, "Compact",
0575 "++ material %-16s add constant property: %s -> %s.",
0576 mat->GetName(), prop_nam.c_str(), ref.c_str());
0577 }
0578 else if ( p.hasAttr(_U(option)) ) {
0579 std::string prop_nam = p.attr<std::string>(_U(name));
0580 std::string prop_typ = p.attr<std::string>(_U(option));
0581 mat->AddConstProperty(prop_nam.c_str(), prop_typ.c_str());
0582 printout(s_debug.materials ? ALWAYS : DEBUG, "Compact",
0583 "++ material %-16s add constant property: %s -> %s.",
0584 mat->GetName(), prop_nam.c_str(), prop_typ.c_str());
0585 }
0586 }
0587
0588 for(xml_coll_t properties(x_mat, _U(property)); properties; ++properties) {
0589 xml_elt_t p = properties;
0590 if ( p.hasAttr(_U(ref)) ) {
0591 std::string ref = p.attr<std::string>(_U(ref));
0592 TGDMLMatrix* gdmlMat = mgr.GetGDMLMatrix(ref.c_str());
0593 if ( gdmlMat ) {
0594 std::string prop_nam = p.attr<std::string>(_U(name));
0595 mat->AddProperty(prop_nam.c_str(), ref.c_str());
0596 printout(s_debug.materials ? ALWAYS : DEBUG, "Compact",
0597 "++ material %-16s add property: %s -> %s.",
0598 mat->GetName(), prop_nam.c_str(), ref.c_str());
0599 continue;
0600 }
0601
0602 throw_print("Compact2Objects[ERROR]: Converting material:" + mname + " Property missing: " + ref);
0603 }
0604 }
0605 }
0606 TGeoMedium* medium = mgr.GetMedium(matname);
0607 if (0 == medium) {
0608 --unique_mat_id;
0609 medium = new TGeoMedium(matname, unique_mat_id, mat);
0610 medium->SetTitle("material");
0611 medium->SetUniqueID(unique_mat_id);
0612 }
0613
0614
0615 if (x_mat.hasAttr(_U(formula))) {
0616 std::string form = x_mat.attr<std::string>(_U(formula));
0617 if (form != matname) {
0618 medium = mgr.GetMedium(form.c_str());
0619 if (0 == medium) {
0620 --unique_mat_id;
0621 medium = new TGeoMedium(form.c_str(), unique_mat_id, mat);
0622 medium->SetTitle("material");
0623 medium->SetUniqueID(unique_mat_id);
0624 }
0625 }
0626 }
0627 }
0628
0629
0630
0631
0632
0633
0634
0635 template <> void Converter<Isotope>::operator()(xml_h e) const {
0636 xml_dim_t isotope(e);
0637 TGeoManager& mgr = description.manager();
0638 std::string nam = isotope.nameStr();
0639 TGeoElementTable* tab = mgr.GetElementTable();
0640 TGeoIsotope* iso = tab->FindIsotope(nam.c_str());
0641
0642
0643 if ( !iso ) {
0644 xml_ref_t atom(isotope.child(_U(atom)));
0645 std::string unit = atom.attr<std::string>(_U(unit));
0646 double value = atom.attr<double>(_U(value));
0647 double a = value * _multiply<double>(unit,"mol/g");
0648 int n = isotope.attr<int>(_U(N));
0649 int z = isotope.attr<int>(_U(Z));
0650 iso = new TGeoIsotope(nam.c_str(), z, n, a);
0651 printout(s_debug.isotopes ? ALWAYS : DEBUG, "Compact",
0652 "++ Converting isotope %-16s Z:%3d N:%3d A:%8.4f [g/mol]",
0653 iso->GetName(), iso->GetZ(), iso->GetN(), iso->GetA());
0654 }
0655 else {
0656 printout(s_debug.isotopes ? WARNING : DEBUG, "Compact",
0657 "++ Isotope %-16s Z:%3d N:%3d A:%8.4f [g/mol] ALREADY defined. [Ignore definition]",
0658 iso->GetName(), iso->GetZ(), iso->GetN(), iso->GetA());
0659 }
0660 }
0661
0662
0663
0664
0665
0666
0667
0668
0669
0670
0671
0672
0673
0674
0675
0676 template <> void Converter<Atom>::operator()(xml_h e) const {
0677 xml_ref_t elem(e);
0678 xml_tag_t name = elem.name();
0679 TGeoManager& mgr = description.manager();
0680 TGeoElementTable* tab = mgr.GetElementTable();
0681 TGeoElement* elt = tab->FindElement(name.c_str());
0682 if ( !elt ) {
0683 if ( elem.hasChild(_U(atom)) ) {
0684 xml_ref_t atom(elem.child(_U(atom)));
0685 std::string formula = elem.attr<std::string>(_U(formula));
0686 double value = atom.attr<double>(_U(value));
0687 std::string unit = atom.attr<std::string>(_U(unit));
0688 int z = elem.attr<int>(_U(Z));
0689 double a = value*_multiply<double>(unit,"mol/g");
0690 printout(s_debug.elements ? ALWAYS : DEBUG, "Compact",
0691 "++ Converting element %-16s [%-3s] Z:%3d A:%8.4f [g/mol]",
0692 name.c_str(), formula.c_str(), z, a);
0693 tab->AddElement(name.c_str(), formula.c_str(), z, a);
0694 }
0695 else {
0696 int num_isotopes = 0;
0697 std::string formula = elem.hasAttr(_U(formula)) ? elem.attr<std::string>(_U(formula)) : name.str();
0698 for( xml_coll_t i(elem,_U(fraction)); i; ++i)
0699 ++num_isotopes;
0700 elt = new TGeoElement(name.c_str(), formula.c_str(), num_isotopes);
0701 tab->AddElement(elt);
0702 for( xml_coll_t i(elem,_U(fraction)); i; ++i) {
0703 double frac = i.attr<double>(_U(n));
0704 std::string ref = i.attr<std::string>(_U(ref));
0705 TGeoIsotope* iso = tab->FindIsotope(ref.c_str());
0706 if ( !iso ) {
0707 except("Compact","Element %s cannot be constructed. Isotope '%s' (fraction: %.3f) missing!",
0708 name.c_str(), ref.c_str(), frac);
0709 }
0710 printout(s_debug.elements ? ALWAYS : DEBUG, "Compact",
0711 "++ Converting element %-16s Add isotope: %-16s fraction:%.4f.",
0712 name.c_str(), ref.c_str(), frac);
0713 elt->AddIsotope(iso, frac);
0714 }
0715 printout(s_debug.elements ? ALWAYS : DEBUG, "Compact",
0716 "++ Converted element %-16s [%-3s] Z:%3d A:%8.4f [g/mol] with %d isotopes.",
0717 name.c_str(), formula.c_str(), elt->Z(), elt->A(), num_isotopes);
0718 }
0719 elt = tab->FindElement(name.c_str());
0720 if (!elt) {
0721 throw_print("Failed to properly insert the Element:"+name+" into the element table!");
0722 }
0723 }
0724 else {
0725 printout(s_debug.elements ? WARNING : DEBUG, "Compact",
0726 "++ Element %-16s Z:%3d N:%3d A:%8.4f [g/mol] ALREADY defined. [Ignore definition]",
0727 elt->GetName(), elt->Z(), elt->N(), elt->A());
0728 }
0729 }
0730
0731
0732
0733
0734
0735
0736
0737
0738 template <> void Converter<STD_Conditions>::operator()(xml_h e) const {
0739 xml_dim_t cond(e);
0740
0741 if ( cond.ptr() ) {
0742 if ( cond.hasAttr(_U(type)) ) {
0743 description.setStdConditions(cond.typeStr());
0744 }
0745 xml_h temperature = cond.child(_U(T), false);
0746 double temp_val = description.stdConditions().temperature;
0747 if ( temperature.ptr() ) {
0748 double temp_unit = _toDouble("kelvin");
0749 if ( temperature.hasAttr(_U(unit)) )
0750 temp_unit = temperature.attr<double>(_U(unit));
0751 temp_val = temperature.attr<double>(_U(value)) * temp_unit;
0752 }
0753 xml_h pressure = cond.child(_U(P), false);
0754 double pressure_val = description.stdConditions().pressure;
0755 if ( pressure.ptr() ) {
0756 double pressure_unit = _toDouble("pascal");
0757 if ( pressure.hasAttr(_U(unit)) )
0758 pressure_unit = pressure.attr<double>(_U(unit));
0759 pressure_val = pressure.attr<double>(_U(value)) * pressure_unit;
0760 }
0761 description.setStdConditions(temp_val, pressure_val);
0762 printout(s_debug.materials ? ALWAYS : DEBUG, "Compact",
0763 "+++ Material standard conditions: Temperature: %.3f Kelvin Pressure: %.3f hPa",
0764 temp_val/_toDouble("kelvin"), pressure_val/_toDouble("hPa"));
0765 }
0766 }
0767
0768
0769
0770
0771
0772 template <> void Converter<OpticalSurface>::operator()(xml_h element) const {
0773 xml_elt_t e = element;
0774 TGeoManager& mgr = description.manager();
0775 std::string sname = e.attr<std::string>(_U(name));
0776 std::string ref, pname;
0777
0778
0779 OpticalSurface::EModel model = OpticalSurface::Model::kMglisur;
0780 OpticalSurface::EFinish finish = OpticalSurface::Finish::kFpolished;
0781 OpticalSurface::EType type = OpticalSurface::Type::kTdielectric_metal;
0782 Double_t value = 1.0;
0783 if ( e.hasAttr(_U(type)) ) type = OpticalSurface::stringToType(e.attr<std::string>(_U(type)));
0784 if ( e.hasAttr(_U(model)) ) model = OpticalSurface::stringToModel(e.attr<std::string>(_U(model)));
0785 if ( e.hasAttr(_U(finish)) ) finish = OpticalSurface::stringToFinish(e.attr<std::string>(_U(finish)));
0786 if ( e.hasAttr(_U(value)) ) value = e.attr<double>(_U(value));
0787 OpticalSurface surf(description, sname, model, finish, type, value);
0788 if ( s_debug.surface ) {
0789 printout(ALWAYS,"Compact","+++ Reading optical surface %s Typ:%d model:%d finish:%d value: %.3f",
0790 sname.c_str(), int(type), int(model), int(finish), value);
0791 }
0792 for (xml_coll_t props(e, _U(property)); props; ++props) {
0793 pname = props.attr<std::string>(_U(name));
0794 if ( props.hasAttr(_U(ref)) ) {
0795 bool err = kFALSE;
0796 ref = props.attr<std::string>(_U(ref));
0797 mgr.GetProperty(ref.c_str(), &err);
0798 surf->AddProperty(pname.c_str(), ref.c_str());
0799 if ( s_debug.surface ) {
0800 printout(ALWAYS,"Compact","+++ \t\t Property: %s -> %s", pname.c_str(), ref.c_str());
0801 }
0802 continue;
0803 }
0804 std::size_t cols = props.attr<long>(_U(coldim));
0805 xml_attr_t opt = props.attr_nothrow(_U(option));
0806 std::stringstream str(props.attr<std::string>(_U(values))), str_nam;
0807 std::string val;
0808 std::vector<double> values;
0809 while ( !str.eof() ) {
0810 val = "";
0811 str >> val;
0812 if ( val.empty() && !str.good() ) break;
0813 values.emplace_back(_toDouble(val));
0814 }
0815
0816 TGDMLMatrix* table = new TGDMLMatrix("",values.size()/cols, cols);
0817 if ( opt ) {
0818 std::string tit = e.attr<std::string>(opt);
0819 str_nam << tit << "|";
0820 }
0821 str_nam << pname << "__" << (void*)table;
0822 table->SetName(str_nam.str().c_str());
0823 table->SetTitle(pname.c_str());
0824 for (std::size_t i=0, n=values.size(); i<n; ++i)
0825 table->Set(i/cols, i%cols, values[i]);
0826 surf->AddProperty(pname.c_str(), table->GetName());
0827 description.manager().AddGDMLMatrix(table);
0828 }
0829 #if ROOT_VERSION_CODE >= ROOT_VERSION(6,31,1)
0830
0831
0832 for(xml_coll_t properties(e, _U(constant)); properties; ++properties) {
0833 xml_elt_t p = properties;
0834 pname = p.attr<std::string>(_U(name));
0835 if ( p.hasAttr(_U(ref)) ) {
0836 bool err = kFALSE;
0837 ref = p.attr<std::string>(_U(ref));
0838 mgr.GetProperty(ref.c_str(), &err);
0839 if ( err == kFALSE ) {
0840 surf->AddConstProperty(pname.c_str(), ref.c_str());
0841 printout(s_debug.surface ? ALWAYS : DEBUG, "Compact",
0842 "++ surface %-16s add constant property: %s -> %s.",
0843 surf->GetName(), pname.c_str(), ref.c_str());
0844 continue;
0845 }
0846
0847 throw_print("Compact2Objects[ERROR]: Converting surface: " + sname +
0848 " ConstProperty missing in TGeoManager: " + ref);
0849 }
0850 else if ( p.hasAttr(_U(value)) ) {
0851 std::stringstream str;
0852 str << pname << "_" << (void*)surf.ptr();
0853 ref = str.str();
0854 mgr.AddProperty(ref.c_str(), p.attr<double>(_U(value)));
0855 surf->AddConstProperty(pname.c_str(), ref.c_str());
0856 printout(s_debug.surface ? ALWAYS : DEBUG, "Compact",
0857 "++ surface %-16s add constant property: %s -> %s.",
0858 surf->GetName(), pname.c_str(), ref.c_str());
0859 }
0860 else if ( p.hasAttr(_U(option)) ) {
0861 std::string ptyp = p.attr<std::string>(_U(option));
0862 surf->AddConstProperty(pname.c_str(), ptyp.c_str());
0863 printout(s_debug.surface ? ALWAYS : DEBUG, "Compact",
0864 "++ surface %-16s add constant property: %s -> %s.",
0865 surf->GetName(), pname.c_str(), ptyp.c_str());
0866 }
0867 }
0868 #endif
0869 }
0870
0871
0872
0873
0874
0875
0876 template <> void Converter<PropertyConstant>::operator()(xml_h e) const {
0877 double value = e.attr<double>(_U(value));
0878 std::string name = e.attr<std::string>(_U(name));
0879 description.manager().AddProperty(name.c_str(), value);
0880 if ( s_debug.matrix ) {
0881 printout(ALWAYS,"Compact","+++ Reading property %s : %f",name.c_str(), value);
0882 }
0883 #if 0
0884 xml_attr_t opt = e.attr_nothrow(_U(title));
0885 if ( opt ) {
0886 std::string val = e.attr<std::string>(opt);
0887 TNamed* nam = description.manager().GetProperty(name.c_str());
0888 if ( !nam ) {
0889 except("Compact","Failed to access just added manager property: %s",name.c_str());
0890 }
0891 nam->SetTitle(val.c_str());
0892 }
0893 #endif
0894 }
0895
0896
0897
0898
0899
0900
0901 template <> void Converter<PropertyTable>::operator()(xml_h e) const {
0902 std::vector<double> vals;
0903 std::size_t cols = e.attr<unsigned long>(_U(coldim));
0904 std::stringstream str(e.attr<std::string>(_U(values)));
0905
0906 if ( s_debug.matrix ) {
0907 printout(ALWAYS,"Compact","+++ Reading property table %s with %d columns.",
0908 e.attr<std::string>(_U(name)).c_str(), cols);
0909 }
0910 vals.reserve(1024);
0911 while ( !str.eof() ) {
0912 std::string item;
0913 str >> item;
0914 if ( item.empty() && !str.good() ) break;
0915 vals.emplace_back(_toDouble(item));
0916 if ( s_debug.matrix ) {
0917 std::cout << " state:" << (str.good() ? "OK " : "BAD") << " '" << item << "'";
0918 if ( 0 == (vals.size()%cols) ) std::cout << std::endl;
0919 }
0920 }
0921 if ( s_debug.matrix ) {
0922 std::cout << std::endl;
0923 }
0924
0925 xml_attr_t opt = e.attr_nothrow(_U(option));
0926 PropertyTable tab(description,
0927 e.attr<std::string>(_U(name)),
0928 opt ? e.attr<std::string>(opt).c_str() : "",
0929 vals.size()/cols, cols);
0930 for( std::size_t i=0, n=vals.size(); i < n; ++i )
0931 tab->Set(i/cols, i%cols, vals[i]);
0932
0933 }
0934
0935
0936
0937
0938
0939
0940
0941
0942
0943
0944
0945
0946
0947
0948
0949 template <> void Converter<VisAttr>::operator()(xml_h e) const {
0950 VisAttr attr(e.attr<std::string>(_U(name)));
0951 float alpha = 1.0;
0952 float red = 1.0;
0953 float green = 1.0;
0954 float blue = 1.0;
0955 bool use_ref = false;
0956 if(e.hasAttr(_U(ref))) {
0957 use_ref = true;
0958 auto refName = e.attr<std::string>(_U(ref));
0959 const auto refAttr = description.visAttributes(refName);
0960 if(!refAttr.isValid() ) {
0961 except("Compact","+++ Reference VisAttr %s does not exist", refName.c_str());
0962 }
0963
0964
0965 refAttr.argb(alpha,red,green,blue);
0966 attr.setColor(alpha,red,green,blue);
0967 attr.setDrawingStyle( refAttr.drawingStyle());
0968 attr.setLineStyle( refAttr.lineStyle());
0969 attr.setShowDaughters(refAttr.showDaughters());
0970 attr.setVisible(refAttr.visible());
0971 }
0972 xml_dim_t dim(e);
0973 alpha = dim.alpha(alpha);
0974 red = dim.r(red );
0975 green = dim.g(green);
0976 blue = dim.b(blue );
0977
0978 printout(s_debug.visattr ? ALWAYS : DEBUG, "Compact",
0979 "++ Converting VisAttr structure: %-16s. Alpha=%.2f R=%.3f G=%.3f B=%.3f",
0980 attr.name(), alpha, red, green, blue);
0981 attr.setColor(alpha, red, green, blue);
0982 if (e.hasAttr(_U(visible)))
0983 attr.setVisible(e.attr<bool>(_U(visible)));
0984 if (e.hasAttr(_U(lineStyle))) {
0985 std::string ls = e.attr<std::string>(_U(lineStyle));
0986 if (ls == "unbroken")
0987 attr.setLineStyle(VisAttr::SOLID);
0988 else if (ls == "broken")
0989 attr.setLineStyle(VisAttr::DASHED);
0990 }
0991 else {
0992 if (!use_ref)
0993 attr.setLineStyle(VisAttr::SOLID);
0994 }
0995 if (e.hasAttr(_U(drawingStyle))) {
0996 std::string ds = e.attr<std::string>(_U(drawingStyle));
0997 if (ds == "wireframe")
0998 attr.setDrawingStyle(VisAttr::WIREFRAME);
0999 else if (ds == "solid")
1000 attr.setDrawingStyle(VisAttr::SOLID);
1001 }
1002 else {
1003 if (!use_ref)
1004 attr.setDrawingStyle(VisAttr::SOLID);
1005 }
1006 if (e.hasAttr(_U(showDaughters)))
1007 attr.setShowDaughters(e.attr<bool>(_U(showDaughters)));
1008 else {
1009 if (!use_ref)
1010 attr.setShowDaughters(true);
1011 }
1012 description.addVisAttribute(attr);
1013 }
1014
1015
1016
1017
1018 template <> void Converter<Region>::operator()(xml_h elt) const {
1019 xml_dim_t e = elt;
1020 Region region(e.nameStr());
1021 auto& limits = region.limits();
1022 xml_attr_t cut = elt.attr_nothrow(_U(cut));
1023 xml_attr_t threshold = elt.attr_nothrow(_U(threshold));
1024 xml_attr_t store_secondaries = elt.attr_nothrow(_U(store_secondaries));
1025 double ene = e.eunit(1.0), len = e.lunit(1.0);
1026
1027 printout(s_debug.regions ? ALWAYS : DEBUG, "Compact",
1028 "++ Converting region structure: %s.",region.name());
1029 if ( cut ) {
1030 region.setCut(elt.attr<double>(cut)*len);
1031 }
1032 if ( threshold ) {
1033 region.setThreshold(elt.attr<double>(threshold)*ene);
1034 }
1035 if ( store_secondaries ) {
1036 region.setStoreSecondaries(elt.attr<bool>(store_secondaries));
1037 }
1038 for (xml_coll_t user_limits(e, _U(limitsetref)); user_limits; ++user_limits)
1039 limits.emplace_back(user_limits.attr<std::string>(_U(name)));
1040 description.addRegion(region);
1041 }
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051 template <> void Converter<Segmentation>::operator()(xml_h seg) const {
1052 std::string type = seg.attr<std::string>(_U(type));
1053 std::string name = seg.hasAttr(_U(name)) ? seg.attr<std::string>(_U(name)) : std::string();
1054 std::pair<Segmentation,IDDescriptor>* opt = _option<std::pair<Segmentation,IDDescriptor> >();
1055
1056 const BitFieldCoder* bitfield = &opt->second->decoder;
1057 Segmentation segment(type, name, bitfield);
1058 if ( segment.isValid() ) {
1059 const DDSegmentation::Parameters& pars = segment.parameters();
1060 printout(s_debug.segmentation ? ALWAYS : DEBUG, "Compact",
1061 "++ Converting segmentation structure: %s of type %s.",name.c_str(),type.c_str());
1062 for(const auto p : pars ) {
1063 xml::Strng_t pNam(p->name());
1064 if ( seg.hasAttr(pNam) ) {
1065 std::string pType = p->type();
1066 if ( pType.compare("int") == 0 ) {
1067 typedef DDSegmentation::TypedSegmentationParameter<int> ParInt;
1068 static_cast<ParInt*>(p)->setTypedValue(seg.attr<int>(pNam));
1069 } else if ( pType.compare("float") == 0 ) {
1070 typedef DDSegmentation::TypedSegmentationParameter<float> ParFloat;
1071 static_cast<ParFloat*>(p)->setTypedValue(seg.attr<float>(pNam));
1072 } else if ( pType.compare("doublevec") == 0 ) {
1073 std::vector<double> valueVector;
1074 std::string par = seg.attr<std::string>(pNam);
1075 printout(s_debug.segmentation ? ALWAYS : DEBUG, "Compact",
1076 "++ Converting this std::string structure: %s.",par.c_str());
1077 std::vector<std::string> elts = DDSegmentation::splitString(par);
1078 for (const std::string& spar : elts ) {
1079 if ( spar.empty() ) continue;
1080 valueVector.emplace_back(_toDouble(spar));
1081 }
1082 typedef DDSegmentation::TypedSegmentationParameter< std::vector<double> > ParDouVec;
1083 static_cast<ParDouVec*>(p)->setTypedValue(valueVector);
1084 } else if ( pType.compare("double" ) == 0) {
1085 typedef DDSegmentation::TypedSegmentationParameter<double>ParDouble;
1086 static_cast<ParDouble*>(p)->setTypedValue(seg.attr<double>(pNam));
1087 } else {
1088 p->setValue(seg.attr<std::string>(pNam));
1089 }
1090 } else if (not p->isOptional()) {
1091 throw_print("FAILED to create segmentation: " + type +
1092 ". Missing mandatory parameter: " + p->name() + "!");
1093 }
1094 }
1095 long key_min = 0, key_max = 0;
1096 DDSegmentation::Segmentation* base = segment->segmentation;
1097 for(xml_coll_t sub(seg,_U(segmentation)); sub; ++sub) {
1098 std::pair<Segmentation,IDDescriptor> sub_object(Segmentation(),opt->second);
1099 Converter<Segmentation> sub_conv(description,param,&sub_object);
1100 sub_conv(sub);
1101 if ( sub_object.first.isValid() ) {
1102 Segmentation sub_seg = sub_object.first;
1103 xml_dim_t x_seg(sub);
1104 if ( sub.hasAttr(_U(key_value)) ) {
1105 key_min = key_max = x_seg.key_value();
1106 }
1107 else if ( sub.hasAttr(_U(key_min)) && sub.hasAttr(_U(key_max)) ) {
1108 key_min = x_seg.key_min();
1109 key_max = x_seg.key_max();
1110 }
1111 else {
1112 std::stringstream tree;
1113 xml::dump_tree(sub,tree);
1114 throw_print("Nested segmentations: Invalid key specification:"+tree.str());
1115 }
1116 printout(s_debug.segmentation ? ALWAYS : DEBUG,"Compact",
1117 "++ Segmentation [%s/%s]: Add sub-segmentation %s [%s]",
1118 name.c_str(), type.c_str(),
1119 sub_seg->segmentation->name().c_str(),
1120 sub_seg->segmentation->type().c_str());
1121 base->addSubsegmentation(key_min, key_max, sub_seg->segmentation);
1122 sub_seg->segmentation = 0;
1123 delete sub_seg.ptr();
1124 }
1125 }
1126 }
1127 opt->first = segment;
1128 }
1129
1130
1131
1132
1133
1134
1135
1136
1137 template <> void Converter<Readout>::operator()(xml_h e) const {
1138 xml_h seg = e.child(_U(segmentation), false);
1139 xml_h id = e.child(_U(id));
1140 std::string name = e.attr<std::string>(_U(name));
1141 std::pair<Segmentation,IDDescriptor> opt;
1142 Readout ro(name);
1143
1144 if (id) {
1145
1146 opt.second = IDDescriptor(name,id.text());
1147 description.addIDSpecification(opt.second);
1148 }
1149 if (seg) {
1150 Converter<Segmentation>(description,param,&opt)(seg);
1151 opt.first->setName(name);
1152 }
1153
1154
1155
1156 if ( opt.first.isValid() ) {
1157 ro.setSegmentation(opt.first);
1158 }
1159 if ( opt.second.isValid() ) {
1160 ro.setIDDescriptor(opt.second);
1161 }
1162
1163 printout(s_debug.readout ? ALWAYS : DEBUG,
1164 "Compact", "++ Converting readout structure: %-16s. %s%s",
1165 ro.name(), id ? "ID: " : "", id ? id.text().c_str() : "");
1166
1167 for(xml_coll_t colls(e,_U(hits_collections)); colls; ++colls) {
1168 std::string hits_key;
1169 if ( colls.hasAttr(_U(key)) ) hits_key = colls.attr<std::string>(_U(key));
1170 for(xml_coll_t coll(colls,_U(hits_collection)); coll; ++coll) {
1171 xml_dim_t c(coll);
1172 std::string coll_name = c.nameStr();
1173 std::string coll_key = hits_key;
1174 long key_min = 0, key_max = 0;
1175
1176 if ( c.hasAttr(_U(key)) ) {
1177 coll_key = c.attr<std::string>(_U(key));
1178 }
1179 if ( c.hasAttr(_U(key_value)) ) {
1180 key_max = key_min = c.key_value();
1181 }
1182 else if ( c.hasAttr(_U(key_min)) && c.hasAttr(_U(key_max)) ) {
1183 key_min = c.key_min();
1184 key_max = c.key_max();
1185 }
1186 else {
1187 std::stringstream tree;
1188 xml::dump_tree(e,tree);
1189 throw_print("Readout: Invalid specification for multiple hit collections."+tree.str());
1190 }
1191 printout(s_debug.readout ? ALWAYS : DEBUG,"Compact",
1192 "++ Readout[%s]: Add hit collection %s [%s] %d-%d",
1193 ro.name(), coll_name.c_str(), coll_key.c_str(), key_min, key_max);
1194 HitCollection hits(coll_name, coll_key, key_min, key_max);
1195 ro->hits.emplace_back(hits);
1196 }
1197 }
1198 description.addReadout(ro);
1199 }
1200
1201 static long load_readout(Detector& description, xml_h element) {
1202 Converter<Readout> converter(description);
1203 converter(element);
1204 return 1;
1205 }
1206 DECLARE_XML_DOC_READER(readout,load_readout)
1207
1208
1209
1210
1211
1212
1213
1214
1215 template <> void Converter<LimitSet>::operator()(xml_h e) const {
1216 Limit limit;
1217 LimitSet ls(e.attr<std::string>(_U(name)));
1218 printout(s_debug.limits ? ALWAYS : DEBUG, "Compact",
1219 "++ Converting LimitSet structure: %s.",ls.name());
1220 for (xml_coll_t c(e, _U(limit)); c; ++c) {
1221 limit.name = c.attr<std::string>(_U(name));
1222 limit.particles = c.attr<std::string>(_U(particles));
1223 limit.content = c.attr<std::string>(_U(value));
1224 limit.unit = c.attr<std::string>(_U(unit));
1225 limit.value = _multiply<double>(limit.content, limit.unit);
1226 ls.addLimit(limit);
1227 printout(s_debug.limits ? ALWAYS : DEBUG, "Compact",
1228 "++ %s: add %-6s: [%s] = %s [%s] = %f",
1229 ls.name(), limit.name.c_str(), limit.particles.c_str(),
1230 limit.content.c_str(), limit.unit.c_str(), limit.value);
1231 }
1232 limit.name = "cut";
1233 for (xml_coll_t c(e, _U(cut)); c; ++c) {
1234 limit.particles = c.attr<std::string>(_U(particles));
1235 limit.content = c.attr<std::string>(_U(value));
1236 limit.unit = c.attr<std::string>(_U(unit));
1237 limit.value = _multiply<double>(limit.content, limit.unit);
1238 ls.addCut(limit);
1239 printout(s_debug.limits ? ALWAYS : DEBUG, "Compact",
1240 "++ %s: add %-6s: [%s] = %s [%s] = %f",
1241 ls.name(), limit.name.c_str(), limit.particles.c_str(),
1242 limit.content.c_str(), limit.unit.c_str(), limit.value);
1243 }
1244 description.addLimitSet(ls);
1245 }
1246
1247
1248
1249
1250
1251
1252
1253 template <> void Converter<Property>::operator()(xml_h e) const {
1254 std::string name = e.attr<std::string>(_U(name));
1255 Detector::Properties& prp = description.properties();
1256 if ( name.empty() )
1257 throw_print("Failed to convert properties. No name given!");
1258
1259 std::vector<xml_attr_t> a = e.attributes();
1260 if ( prp.find(name) == prp.end() )
1261 prp.emplace(name, Detector::PropertyValues());
1262
1263 for (xml_attr_t i : a )
1264 prp[name].emplace(xml_tag_t(e.attr_name(i)).str(),e.attr<std::string>(i));
1265 }
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275 template <> void Converter<CartesianField>::operator()(xml_h e) const {
1276 std::string msg = "updated";
1277 std::string name = e.attr<std::string>(_U(name));
1278 std::string type = e.attr<std::string>(_U(type));
1279 CartesianField field = description.field(name);
1280 if ( !field.isValid() ) {
1281
1282 field = Ref_t(PluginService::Create<NamedObject*>(type, &description, &e));
1283 if ( !field.isValid() ) {
1284 PluginDebug dbg;
1285 PluginService::Create<NamedObject*>(type, &description, &e);
1286 throw_print("Failed to create field object of type "+type + ". "+dbg.missingFactory(type));
1287 }
1288 description.addField(field);
1289 msg = "created";
1290 }
1291 type = field.type();
1292
1293 CartesianField::Properties& prp = field.properties();
1294 for ( xml_coll_t c(e, _U(properties)); c; ++c ) {
1295 std::string props_name = c.attr<std::string>(_U(name));
1296 std::vector<xml_attr_t>a = c.attributes();
1297 if ( prp.find(props_name) == prp.end() ) {
1298 prp.emplace(props_name, Detector::PropertyValues());
1299 }
1300 for ( xml_attr_t i : a )
1301 prp[props_name].emplace(xml_tag_t(c.attr_name(i)).str(), c.attr<std::string>(i));
1302
1303 if (c.hasAttr(_U(global)) && c.attr<bool>(_U(global))) {
1304 description.field().properties() = prp;
1305 }
1306 }
1307 printout(INFO, "Compact", "++ Converted field: Successfully %s field %s [%s]", msg.c_str(), name.c_str(), type.c_str());
1308 }
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323 template <> void Converter<SensitiveDetector>::operator()(xml_h element) const {
1324 std::string name = element.attr<std::string>(_U(name));
1325 try {
1326 SensitiveDetector sd = description.sensitiveDetector(name);
1327 xml_attr_t type = element.attr_nothrow(_U(type));
1328 if ( type ) {
1329 sd.setType(element.attr<std::string>(type));
1330 }
1331 xml_attr_t verbose = element.attr_nothrow(_U(verbose));
1332 if ( verbose ) {
1333 sd.setVerbose(element.attr<bool>(verbose));
1334 }
1335 xml_attr_t combine = element.attr_nothrow(_U(combine_hits));
1336 if ( combine ) {
1337 sd.setCombineHits(element.attr<bool>(combine));
1338 }
1339 xml_attr_t limits = element.attr_nothrow(_U(limits));
1340 if ( limits ) {
1341 std::string l = element.attr<std::string>(limits);
1342 LimitSet ls = description.limitSet(l);
1343 if (!ls.isValid()) {
1344 throw_print("Converter<SensitiveDetector>: Request for non-existing limitset:" + l);
1345 }
1346 sd.setLimitSet(ls);
1347 }
1348 xml_attr_t region = element.attr_nothrow(_U(region));
1349 if ( region ) {
1350 std::string r = element.attr<std::string>(region);
1351 Region reg = description.region(r);
1352 if (!reg.isValid()) {
1353 throw_print("Converter<SensitiveDetector>: Request for non-existing region:" + r);
1354 }
1355 sd.setRegion(reg);
1356 }
1357 xml_attr_t hits = element.attr_nothrow(_U(hits_collection));
1358 if (hits) {
1359 sd.setHitsCollection(element.attr<std::string>(hits));
1360 }
1361 xml_attr_t ecut = element.attr_nothrow(_U(ecut));
1362 xml_attr_t eunit = element.attr_nothrow(_U(eunit));
1363 if (ecut && eunit) {
1364 double value = _multiply<double>(_toString(ecut), _toString(eunit));
1365 sd.setEnergyCutoff(value);
1366 }
1367 else if (ecut) {
1368 sd.setEnergyCutoff(element.attr<double>(ecut));
1369 }
1370 printout(DEBUG, "Compact", "SensitiveDetector-update: %-18s %-24s Hits:%-24s Cutoff:%7.3f", sd.name(),
1371 (" [" + sd.type() + "]").c_str(), sd.hitsCollection().c_str(), sd.energyCutoff());
1372 xml_attr_t sequence = element.attr_nothrow(_U(sequence));
1373 if (sequence) {
1374 }
1375 }
1376 catch (const std::exception& e) {
1377 printout(ERROR, "Compact", "++ FAILED to convert sensitive detector: %s: %s", name.c_str(), e.what());
1378 }
1379 catch (...) {
1380 printout(ERROR, "Compact", "++ FAILED to convert sensitive detector: %s: %s", name.c_str(), "UNKNONW Exception");
1381 }
1382 }
1383
1384 static void setChildTitles(const std::pair<std::string, DetElement>& e) {
1385 DetElement parent = e.second.parent();
1386 const DetElement::Children& children = e.second.children();
1387 if (::strlen(e.second->GetTitle()) == 0) {
1388 e.second->SetTitle(parent.isValid() ? parent.type().c_str() : e.first.c_str());
1389 }
1390 for_each(children.begin(), children.end(), setChildTitles);
1391 }
1392
1393 template <> void Converter<DetElement>::operator()(xml_h element) const {
1394 static const char* req_dets = ::getenv("REQUIRED_DETECTORS");
1395 static const char* req_typs = ::getenv("REQUIRED_DETECTOR_TYPES");
1396 static const char* ign_dets = ::getenv("IGNORED_DETECTORS");
1397 static const char* ign_typs = ::getenv("IGNORED_DETECTOR_TYPES");
1398 std::string type = element.attr<std::string>(_U(type));
1399 std::string name = element.attr<std::string>(_U(name));
1400 std::string name_match = ":" + name + ":";
1401 std::string type_match = ":" + type + ":";
1402
1403 if (req_dets && !strstr(req_dets, name_match.c_str()))
1404 return;
1405 if (req_typs && !strstr(req_typs, type_match.c_str()))
1406 return;
1407 if (ign_dets && strstr(ign_dets, name_match.c_str()))
1408 return;
1409 if (ign_typs && strstr(ign_typs, type_match.c_str()))
1410 return;
1411 xml_attr_t attr_ignore = element.attr_nothrow(_U(ignore));
1412 if ( attr_ignore ) {
1413 bool ignore_det = element.attr<bool>(_U(ignore));
1414 if ( ignore_det ) {
1415 printout(INFO, "Compact",
1416 "+++ Do not build subdetector:%s [ignore flag set]",
1417 name.c_str());
1418 return;
1419 }
1420 }
1421 try {
1422 std::string par_name;
1423 xml_attr_t attr_par = element.attr_nothrow(_U(parent));
1424 xml_elt_t elt_par(0);
1425 if (attr_par)
1426 par_name = element.attr<std::string>(attr_par);
1427 else if ( (elt_par=element.child(_U(parent),false)) )
1428 par_name = elt_par.attr<std::string>(_U(name));
1429 if ( !par_name.empty() ) {
1430
1431
1432
1433 if ( par_name[0] == '$' ) par_name = xml::getEnviron(par_name);
1434 DetElement parent = description.detector(par_name);
1435 if ( !parent.isValid() ) {
1436 except("Compact","Failed to access valid parent detector of %s",name.c_str());
1437 }
1438 description.declareParent(name, parent);
1439 }
1440 if( s_debug.detelements ) {
1441 printout(ALWAYS, "Compact","++ Building DetElement %s of type: %s. Parent: %s",
1442 name.c_str(), type.c_str(), par_name.c_str());
1443 }
1444
1445 xml_attr_t attr_ro = element.attr_nothrow(_U(readout));
1446 SensitiveDetector sd;
1447 Segmentation seg;
1448 if ( attr_ro ) {
1449 Readout ro = description.readout(element.attr<std::string>(attr_ro));
1450 if (!ro.isValid()) {
1451 except("Compact","No Readout structure present for detector:" + name);
1452 }
1453 seg = ro.segmentation();
1454 sd = SensitiveDetector(name, "sensitive");
1455 sd.setHitsCollection(ro.name());
1456 sd.setReadout(ro);
1457 description.addSensitiveDetector(sd);
1458 }
1459 Ref_t sens = sd;
1460 DetElement det(Ref_t(PluginService::Create<NamedObject*>(type, &description, &element, &sens)));
1461 if (det.isValid()) {
1462 setChildTitles(std::make_pair(name, det));
1463 if ( sd.isValid() ) {
1464 det->flag |= DetElement::Object::HAVE_SENSITIVE_DETECTOR;
1465 }
1466 if ( seg.isValid() ) {
1467 seg->sensitive = sd;
1468 seg->detector = det;
1469 }
1470 }
1471 printout(det.isValid() ? INFO : ERROR, "Compact", "%s subdetector:%s of type %s %s",
1472 (det.isValid() ? "++ Converted" : "FAILED "), name.c_str(), type.c_str(),
1473 (sd.isValid() ? ("[" + sd.type() + "]").c_str() : ""));
1474
1475 if (!det.isValid()) {
1476 PluginDebug dbg;
1477 PluginService::Create<NamedObject*>(type, &description, &element, &sens);
1478 except("Compact","Failed to execute subdetector creation plugin. %s", dbg.missingFactory(type).c_str());
1479 }
1480 description.addDetector(det);
1481 description.surfaceManager().registerSurfaces(det);
1482 return;
1483 }
1484 catch (const std::exception& e) {
1485 printout(ERROR, "Compact", "++ FAILED to convert subdetector: %s: %s", name.c_str(), e.what());
1486 std::terminate();
1487 }
1488 catch (...) {
1489 printout(ERROR, "Compact", "++ FAILED to convert subdetector: %s: %s", name.c_str(), "UNKNONW Exception");
1490 std::terminate();
1491 }
1492 }
1493
1494
1495 template <> void Converter<IncludeFile>::operator()(xml_h element) const {
1496 xml::DocumentHolder doc(xml::DocumentHandler().load(element, element.attr_value(_U(ref))));
1497 if ( s_debug.include_guard) {
1498
1499 if (check_process_file(description, doc.uri()))
1500 return;
1501 }
1502 xml_h root = doc.root();
1503 if ( s_debug.includes ) {
1504 printout(ALWAYS, "Compact","++ Processing xml document %s.",doc.uri().c_str());
1505 }
1506 if ( root.tag() == "materials" || root.tag() == "elements" ) {
1507 xml_coll_t(root, _U(isotope)).for_each(Converter<Isotope>(this->description,0,0));
1508 xml_coll_t(root, _U(element)).for_each(Converter<Atom>(this->description));
1509 xml_coll_t(root, _U(material)).for_each(Converter<Material>(this->description));
1510 return;
1511 }
1512 this->description.fromXML(doc.uri(), this->description.buildType());
1513 }
1514
1515
1516 template <> void Converter<JsonFile>::operator()(xml_h element) const {
1517 std::string base = xml::DocumentHandler::system_directory(element);
1518 std::string file = element.attr<std::string>(_U(ref));
1519 std::vector<char*> argv{&file[0], &base[0]};
1520 description.apply("DD4hep_JsonProcessor",int(argv.size()), &argv[0]);
1521 }
1522
1523
1524 template <> void Converter<XMLFile>::operator()(xml_h element) const {
1525 PrintLevel level = s_debug.includes ? ALWAYS : DEBUG;
1526 std::string fname = element.attr<std::string>(_U(ref));
1527 std::size_t idx = fname.find("://");
1528 std::error_code ec;
1529
1530 if ( idx == std::string::npos && std::filesystem::exists(fname, ec) ) {
1531
1532 printout(level, "Compact","++ Processing xml document %s.", fname.c_str());
1533 this->description.fromXML(fname, this->description.buildType());
1534 }
1535 else if ( idx == std::string::npos ) {
1536
1537 std::string location = xml::DocumentHandler::system_path(element, fname);
1538 printout(level, "Compact","++ Processing xml document %s.", location.c_str());
1539 this->description.fromXML(location, this->description.buildType());
1540 }
1541 else if ( idx > 0 ) {
1542
1543 printout(level, "Compact","++ Processing xml document %s.", fname.c_str());
1544 this->description.fromXML(fname, this->description.buildType());
1545 }
1546 else {
1547
1548 printout(level, "Compact","++ Processing xml document %s.", fname.c_str());
1549 this->description.fromXML(fname, this->description.buildType());
1550 }
1551 }
1552
1553
1554 template <> void Converter<World>::operator()(xml_h element) const {
1555 xml_elt_t x_world(element);
1556 xml_comp_t x_shape = x_world.child(_U(shape), false);
1557 xml_attr_t att = x_world.getAttr(_U(material));
1558 Material mat = att ? description.material(x_world.attr<std::string>(att)) : description.air();
1559 Volume world_vol;
1560
1561
1562 if ( x_shape ) {
1563 Solid sol(x_shape.createShape());
1564 world_vol = Volume("world_volume", sol, mat);
1565 printout(INFO, "Compact", "++ Created successfully world volume '%s'. shape: %s material:%s.",
1566 world_vol.name(), sol.type(), mat.name());
1567 description.manager().SetTopVolume(world_vol.ptr());
1568 }
1569 else {
1570 world_vol = description.worldVolume();
1571 if ( !world_vol && att ) {
1572
1573
1574 Box sol("world_x", "world_y", "world_z");
1575 world_vol = Volume("world_volume", sol, mat);
1576 printout(INFO, "Compact", "++ Created world volume '%s' as %s (%.2f, %.2f %.2f [cm]) material:%s.",
1577 world_vol.name(), sol.type(),
1578 sol.x()/dd4hep::cm, sol.y()/dd4hep::cm, sol.z()/dd4hep::cm,
1579 mat.name());
1580 description.manager().SetTopVolume(world_vol.ptr());
1581 }
1582 else if ( !world_vol ) {
1583 except("Compact", "++ Logical error: "
1584 "You cannot configure the world volume before it is created and not giving creation instructions.");
1585 }
1586 }
1587
1588 if ( world_vol.isValid() ) {
1589 xml::configVolume(description, x_world, world_vol, false, true);
1590 auto vis = world_vol.visAttributes();
1591 if ( !vis.isValid() ) {
1592 vis = description.visAttributes("WorldVis");
1593 world_vol.setVisAttributes(vis);
1594 }
1595 }
1596 }
1597
1598
1599 template <> void Converter<Parallelworld_Volume>::operator()(xml_h element) const {
1600 xml_det_t parallel(element);
1601 xml_comp_t shape = parallel.child(_U(shape));
1602 xml_dim_t pos = element.child(_U(position),false);
1603 xml_dim_t rot = element.child(_U(rotation),false);
1604 std::string name = element.attr<std::string>(_U(name));
1605 std::string path = element.attr<std::string>(_U(anchor));
1606 bool conn = element.attr<bool>(_U(connected),false);
1607 DetElement anchor(detail::tools::findElement(description, path));
1608 Position position = pos ? Position(pos.x(), pos.y(), pos.z()) : Position();
1609 RotationZYX rotation = rot ? RotationZYX(rot.z(), rot.y(), rot.x()) : RotationZYX();
1610
1611 Material mat = parallel.hasAttr(_U(material))
1612 ? description.material(parallel.attr<std::string>(_U(material)))
1613 : description.air();
1614 VisAttr vis = parallel.hasAttr(_U(vis))
1615 ? description.invisible()
1616 : description.visAttributes(parallel.visStr());
1617
1618 if ( !anchor.isValid() ) {
1619 except("Parallelworld_Volume",
1620 "++ FAILED Cannot identify the anchor of the tracking volume: '%s'",
1621 path.c_str());
1622 }
1623
1624
1625 Transform3D tr_volume(detail::matrix::_transform(anchor.nominal().worldTransformation().Inverse()));
1626 Solid sol(shape.createShape());
1627 Volume vol(name, sol, mat);
1628 Volume par = conn ? description.worldVolume() : description.parallelWorldVolume();
1629 PlacedVolume pv;
1630
1631
1632 vol.setVisAttributes(vis);
1633
1634 vol.setFlagBit(Volume::VETO_SIMU);
1635
1636
1637 Transform3D trafo = tr_volume * Transform3D(rotation,position);
1638 pv = par.placeVolume(vol, trafo);
1639 if ( !pv.isValid() ) {
1640 except("Parallelworld_Volume",
1641 "++ FAILED to place the tracking volume inside the anchor '%s'",path.c_str());
1642 }
1643 if ( name == "tracking_volume" ) {
1644 description.setTrackingVolume(vol);
1645 }
1646 printout(INFO, "Compact", "++ Converted successfully parallelworld_volume %s. anchor: %s vis:%s.",
1647 vol.name(), anchor.path().c_str(), vis.name());
1648 }
1649
1650
1651 template <> void Converter<DetElementInclude>::operator()(xml_h element) const {
1652 std::string type = element.hasAttr(_U(type)) ? element.attr<std::string>(_U(type)) : std::string("xml");
1653 if ( type == "xml" ) {
1654 xml::DocumentHolder doc(xml::DocumentHandler().load(element, element.attr_value(_U(ref))));
1655 if ( s_debug.include_guard ) {
1656
1657 if (check_process_file(description, doc.uri()))
1658 return;
1659 }
1660 if ( s_debug.includes ) {
1661 printout(ALWAYS, "Compact","++ Processing xml document %s.",doc.uri().c_str());
1662 }
1663 xml_h node = doc.root();
1664 std::string tag = node.tag();
1665 if ( tag == "lccdd" )
1666 Converter<Compact>(this->description)(node);
1667 else if ( tag == "define" )
1668 xml_coll_t(node, _U(constant)).for_each(Converter<Constant>(this->description));
1669 else if ( tag == "readout" )
1670 Converter<Readout>(this->description)(node);
1671 else if ( tag == "readouts" )
1672 xml_coll_t(node, _U(readout)).for_each(Converter<Readout>(this->description));
1673 else if ( tag == "region" )
1674 Converter<Region>(this->description)(node);
1675 else if ( tag == "regions" )
1676 xml_coll_t(node, _U(region)).for_each(Converter<Region>(this->description));
1677 else if ( tag == "limits" || tag == "limitsets" )
1678 xml_coll_t(node, _U(limitset)).for_each(Converter<LimitSet>(this->description));
1679 else if ( tag == "display" )
1680 xml_coll_t(node,_U(vis)).for_each(Converter<VisAttr>(this->description));
1681 else if ( tag == "detector" )
1682 Converter<DetElement>(this->description)(node);
1683 else if ( tag == "detectors" )
1684 xml_coll_t(node,_U(detector)).for_each(Converter<DetElement>(this->description));
1685 }
1686 else if ( type == "json" ) {
1687 Converter<JsonFile>(this->description)(element);
1688 }
1689 else if ( type == "gdml" ) {
1690 Converter<IncludeFile>(this->description)(element);
1691 }
1692 else if ( type == "include" ) {
1693 Converter<IncludeFile>(this->description)(element);
1694 }
1695 else if ( type == "xml-extended" ) {
1696 Converter<XMLFile>(this->description)(element);
1697 }
1698 else {
1699 except("Compact","++ FAILED Invalid file type:%s. This cannot be processed!",type.c_str());
1700 }
1701 }
1702
1703
1704 template <> void Converter<Compact>::operator()(xml_h element) const {
1705 static int num_calls = 0;
1706 std::string close_option;
1707 char text[32];
1708
1709 ++num_calls;
1710 xml_elt_t compact(element);
1711 bool steer_geometry = compact.hasChild(_U(geometry));
1712 bool open_geometry = true;
1713 bool close_document = true;
1714 bool close_geometry = true;
1715 bool build_reflections = false;
1716 xml_dim_t world = element.child(_U(world), false);
1717
1718
1719 if (element.hasChild(_U(debug)))
1720 (Converter<Debug>(description))(xml_h(compact.child(_U(debug))));
1721
1722 if ( steer_geometry ) {
1723 xml_elt_t steer = compact.child(_U(geometry));
1724 if ( steer.hasAttr(_U(open)) )
1725 open_geometry = steer.attr<bool>(_U(open));
1726 if ( steer.hasAttr(_U(close)) )
1727 close_document = steer.attr<bool>(_U(close));
1728 if ( steer.hasAttr(_U(reflect)) )
1729 build_reflections = steer.attr<bool>(_U(reflect));
1730 if ( steer.hasAttr(_U(option)) )
1731 close_option = steer.attr<std::string>(_U(option));
1732
1733 for (xml_coll_t clr(steer, _U(clear)); clr; ++clr) {
1734 std::string nam = clr.hasAttr(_U(name)) ? clr.attr<std::string>(_U(name)) : std::string();
1735 if ( nam.substr(0,6) == "elemen" ) {
1736 TGeoElementTable* table = description.manager().GetElementTable();
1737 table->TGeoElementTable::~TGeoElementTable();
1738 new(table) TGeoElementTable();
1739
1740 table->AddElement("VACUUM","VACUUM" ,0, 0, 0.0);
1741 printout(INFO,"Compact",
1742 "++ Cleared default ROOT TGeoElementTable contents. "
1743 "Must now be filled from XML!");
1744 }
1745 }
1746 }
1747
1748 if ( s_debug.materials || s_debug.elements ) {
1749 printout(INFO,"Compact","+++ UNIT System:");
1750 printout(INFO,"Compact","+++ Density: %8.3g Units:%8.3g",
1751 xml::_toDouble(_Unicode(gram/cm3)), dd4hep::gram/dd4hep::cm3);
1752 printout(INFO,"Compact","+++ GeV: %8.3g Units:%8.3g",xml::_toDouble(_Unicode(GeV)),dd4hep::GeV);
1753 printout(INFO,"Compact","+++ sec: %8.3g Units:%8.3g",xml::_toDouble(_Unicode(second)),dd4hep::second);
1754 printout(INFO,"Compact","+++ nanosecond: %8.3g Units:%8.3g",xml::_toDouble(_Unicode(nanosecond)),dd4hep::nanosecond);
1755 printout(INFO,"Compact","+++ kilo: %8.3g Units:%8.3g",xml::_toDouble(_Unicode(kilogram)),dd4hep::kilogram);
1756 printout(INFO,"Compact","+++ kilo: %8.3g Units:%8.3g",xml::_toDouble(_Unicode(joule*s*s/(m*m))),
1757 dd4hep::joule*dd4hep::s*dd4hep::s/(dd4hep::meter*dd4hep::meter));
1758 printout(INFO,"Compact","+++ meter: %8.3g Units:%8.3g",xml::_toDouble(_Unicode(meter)),dd4hep::meter);
1759 printout(INFO,"Compact","+++ ampere: %8.3g Units:%8.3g",xml::_toDouble(_Unicode(ampere)),dd4hep::ampere);
1760 printout(INFO,"Compact","+++ degree: %8.3g Units:%8.3g",xml::_toDouble(_Unicode(degree)),dd4hep::degree);
1761 }
1762
1763 xml_coll_t(compact, _U(define)).for_each(_U(include), Converter<DetElementInclude>(description));
1764 xml_coll_t(compact, _U(define)).for_each(_U(constant), Converter<Constant>(description));
1765 xml_coll_t(compact, _U(std_conditions)).for_each( Converter<STD_Conditions>(description));
1766 xml_coll_t(compact, _U(includes)).for_each(_U(gdmlFile), Converter<IncludeFile>(description));
1767 xml_coll_t(compact, _U(includes)).for_each(_U(file), Converter<IncludeFile>(description));
1768
1769 if (element.hasChild(_U(info)))
1770 (Converter<Header>(description))(xml_h(compact.child(_U(info))));
1771
1772
1773 xml_coll_t(compact, _U(properties)).for_each(_U(attributes), Converter<Property>(description));
1774 xml_coll_t(compact, _U(properties)).for_each(_U(constant), Converter<PropertyConstant>(description));
1775 xml_coll_t(compact, _U(properties)).for_each(_U(matrix), Converter<PropertyTable>(description));
1776 xml_coll_t(compact, _U(properties)).for_each(_U(plugin), Converter<Plugin> (description));
1777 xml_coll_t(compact, _U(surfaces)).for_each(_U(opticalsurface), Converter<OpticalSurface>(description));
1778
1779 xml_coll_t(compact, _U(materials)).for_each(_U(element), Converter<Atom>(description));
1780 xml_coll_t(compact, _U(materials)).for_each(_U(material), Converter<Material>(description));
1781 xml_coll_t(compact, _U(materials)).for_each(_U(plugin), Converter<Plugin> (description));
1782
1783 printout(DEBUG, "Compact", "++ Converting visualization attributes...");
1784 xml_coll_t(compact, _U(display)).for_each(_U(include), Converter<DetElementInclude>(description));
1785 xml_coll_t(compact, _U(display)).for_each(_U(vis), Converter<VisAttr>(description));
1786
1787 printout(DEBUG, "Compact", "++ Converting limitset structures...");
1788 xml_coll_t(compact, _U(limits)).for_each(_U(include), Converter<DetElementInclude>(description));
1789 xml_coll_t(compact, _U(limits)).for_each(_U(limitset), Converter<LimitSet>(description));
1790
1791 printout(DEBUG, "Compact", "++ Converting region structures...");
1792 xml_coll_t(compact, _U(regions)).for_each(_U(include), Converter<DetElementInclude>(description));
1793 xml_coll_t(compact, _U(regions)).for_each(_U(region), Converter<Region>(description));
1794
1795 if ( world ) {
1796 (Converter<World>(description))(world);
1797 }
1798 if ( open_geometry ) description.init();
1799 printout(DEBUG, "Compact", "++ Converting readout structures...");
1800 xml_coll_t(compact, _U(readouts)).for_each(_U(include), Converter<DetElementInclude>(description));
1801 xml_coll_t(compact, _U(readouts)).for_each(_U(readout), Converter<Readout>(description));
1802
1803 printout(DEBUG, "Compact", "++ Converting included files with subdetector structures...");
1804 xml_coll_t(compact, _U(detectors)).for_each(_U(include), Converter<DetElementInclude>(description));
1805 printout(DEBUG, "Compact", "++ Converting detector structures...");
1806 xml_coll_t(compact, _U(detectors)).for_each(_U(detector), Converter<DetElement>(description));
1807 xml_coll_t(compact, _U(include)).for_each(Converter<DetElementInclude>(this->description));
1808
1809 xml_coll_t(compact, _U(includes)).for_each(_U(xml), Converter<XMLFile>(description));
1810 xml_coll_t(compact, _U(fields)).for_each(_U(field), Converter<CartesianField>(description));
1811 xml_coll_t(compact, _U(sensitive_detectors)).for_each(_U(sd), Converter<SensitiveDetector>(description));
1812 xml_coll_t(compact, _U(parallelworld_volume)).for_each(Converter<Parallelworld_Volume>(description));
1813
1814 if ( --num_calls == 0 && close_document ) {
1815 ::snprintf(text, sizeof(text), "%u", xml_h(element).checksum(0));
1816 description.addConstant(Constant("compact_checksum", text));
1817 if( close_geometry ) close_option += "close";
1818 description.endDocument(close_option.c_str());
1819 }
1820 if ( build_reflections ) {
1821 ReflectionBuilder rb(description);
1822 rb.execute();
1823 }
1824
1825 xml_coll_t(compact, _U(plugins)).for_each(_U(plugin), Converter<Plugin> (description));
1826 xml_coll_t(compact, _U(plugins)).for_each(_U(include), Converter<XMLFile> (description));
1827 xml_coll_t(compact, _U(plugins)).for_each(_U(xml), Converter<XMLFile> (description));
1828 }
1829
1830 #ifdef _WIN32
1831 template Converter<Plugin>;
1832 template Converter<Constant>;
1833 template Converter<Material>;
1834 template Converter<Atom>;
1835 template Converter<VisAttr>;
1836 template Converter<Region>;
1837 template Converter<Readout>;
1838 template Converter<Segmentation>;
1839 template Converter<LimitSet>;
1840 template Converter<Property>;
1841 template Converter<CartesianField>;
1842 template Converter<SensitiveDetector>;
1843 template Converter<DetElement>;
1844 template Converter<GdmlFile>;
1845 template Converter<XMLFile>;
1846 template Converter<Header>;
1847 template Converter<DetElementInclude>;
1848 template Converter<Compact>;
1849
1850 #endif