File indexing completed on 2025-07-05 08:13:39
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include "LCDDConverter.h"
0016 #include <DD4hep/Plugins.h>
0017 #include <DD4hep/Printout.h>
0018 #include <DD4hep/Volumes.h>
0019 #include <DD4hep/FieldTypes.h>
0020 #include <DD4hep/DD4hepUnits.h>
0021 #include <DD4hep/Segmentations.h>
0022 #include <DD4hep/detail/ObjectsInterna.h>
0023 #include <DD4hep/detail/DetectorInterna.h>
0024 #include <XML/DocumentHandler.h>
0025
0026
0027 #include <TROOT.h>
0028 #include <TColor.h>
0029 #include <TGeoShape.h>
0030
0031 #include <TGeoArb8.h>
0032 #include <TGeoBoolNode.h>
0033 #include <TGeoCompositeShape.h>
0034 #include <TGeoCone.h>
0035 #include <TGeoEltu.h>
0036 #include <TGeoHype.h>
0037 #include <TGeoMatrix.h>
0038 #include <TGeoParaboloid.h>
0039 #include <TGeoPara.h>
0040 #include <TGeoPcon.h>
0041 #include <TGeoPgon.h>
0042 #include <TGeoShapeAssembly.h>
0043 #include <TGeoSphere.h>
0044 #include <TGeoTorus.h>
0045 #include <TGeoTrd1.h>
0046 #include <TGeoTrd2.h>
0047 #include <TGeoTube.h>
0048 #include <TGeoScaledShape.h>
0049
0050 #include <TGeoNode.h>
0051 #include <TClass.h>
0052 #include <TMath.h>
0053
0054
0055 #include <fstream>
0056 #include <iostream>
0057 #include <sstream>
0058
0059 using namespace dd4hep;
0060 using namespace dd4hep::detail;
0061
0062 namespace {
0063 typedef Position XYZRotation;
0064
0065 XYZRotation getXYZangles(const Double_t* r) {
0066 Double_t cosb = std::sqrt(r[0]*r[0] + r[1]*r[1]);
0067 if (cosb > 0.00001) {
0068 return XYZRotation(atan2(r[5], r[8]), atan2(-r[2], cosb), atan2(r[1], r[0]));
0069 }
0070 return XYZRotation(atan2(-r[7], r[4]),atan2(-r[2], cosb),0);
0071 }
0072
0073 #if 0
0074 XYZRotation getXYZangles(const Double_t* rotationMatrix) {
0075 Double_t a, b, c;
0076 Double_t rad = 1.0;
0077 const Double_t *r = rotationMatrix;
0078 Double_t cosb = TMath::Sqrt(r[0] * r[0] + r[1] * r[1]);
0079 if (cosb > 0.00001) {
0080 a = TMath::ATan2(r[5], r[8]) * rad;
0081 b = TMath::ATan2(-r[2], cosb) * rad;
0082 c = TMath::ATan2(r[1], r[0]) * rad;
0083 }
0084 else {
0085 a = TMath::ATan2(-r[7], r[4]) * rad;
0086 b = TMath::ATan2(-r[2], cosb) * rad;
0087 c = 0;
0088 }
0089 XYZRotation rr(a, b, c);
0090 std::cout << " X:" << a << " " << rr.X() << " Y:" << b << " " << rr.Y() << " Z:" << c << " " << rr.Z()
0091 << " lx:" << r[0] << " ly:" << r[4] << " lz:" << r[8] << std::endl;
0092 return XYZRotation(a, b, c);
0093 }
0094 #endif
0095
0096 bool is_volume(const TGeoVolume* volume) {
0097 Volume v(volume);
0098 return v.data() != 0;
0099 }
0100 bool is_placement(PlacedVolume node) {
0101 return node.data() != 0;
0102 }
0103
0104 std::string genName(const std::string& n) { return n; }
0105 std::string genName(const std::string& n, const void* ptr) {
0106 std::string nn = genName(n);
0107 char text[32];
0108 ::snprintf(text,sizeof(text),"%p",ptr);
0109 nn += "_";
0110 nn += text;
0111 return nn;
0112 }
0113 }
0114
0115 void LCDDConverter::GeometryInfo::check(const std::string& name, const TNamed* _n, std::map<std::string, const TNamed*>& _m) const {
0116 std::map<std::string, const TNamed*>::const_iterator i = _m.find(name);
0117 if (i != _m.end()) {
0118 const char* isa = _n ? _n->IsA()->GetName() : (*i).second ? (*i).second->IsA()->GetName() : "Unknown";
0119 std::cout << isa << "(position): duplicate entry with name:" << name << " " << (void*) _n << " " << (void*) (*i).second << std::endl;
0120 }
0121 _m.insert(make_pair(name, _n));
0122 }
0123
0124
0125 LCDDConverter::LCDDConverter(Detector& description)
0126 : m_detDesc(description), m_dataPtr(0) {
0127 }
0128
0129 LCDDConverter::~LCDDConverter() {
0130 if (m_dataPtr)
0131 delete m_dataPtr;
0132 m_dataPtr = 0;
0133 }
0134
0135
0136 xml_h LCDDConverter::handleElement(const std::string& , Atom element) const {
0137 GeometryInfo& geo = data();
0138 xml_h e = geo.xmlElements[element];
0139 if (!e) {
0140 int Z = element->Z();
0141 double A = element->A();
0142 xml_elt_t atom(geo.doc, _U(atom));
0143
0144
0145 geo.doc_materials.append(e = xml_elt_t(geo.doc, _U(element)));
0146 e.append(atom);
0147 e.setAttr(_U(name), element->GetName());
0148 e.setAttr(_U(formula), element->GetName());
0149 e.setAttr(_U(Z), Z>0 ? Z : 1);
0150 atom.setAttr(_U(type), "A");
0151 atom.setAttr(_U(unit), "g/mol");
0152 atom.setAttr(_U(value), A>0.99 ? A : 1.00794 );
0153 geo.xmlElements[element] = e;
0154 }
0155 return e;
0156 }
0157
0158
0159 xml_h LCDDConverter::handleMaterial(const std::string& name, Material medium) const {
0160 GeometryInfo& geo = data();
0161 xml_h mat = geo.xmlMaterials[medium];
0162 if (!mat) {
0163 xml_h obj;
0164 TGeoMaterial* geo_mat = medium->GetMaterial();
0165 double d = geo_mat->GetDensity();
0166 if (d < 1e-10) d = 1e-10;
0167 mat = xml_elt_t(geo.doc, _U(material));
0168 mat.setAttr(_U(name), medium->GetName());
0169 mat.append(obj = xml_elt_t(geo.doc, _U(D)));
0170 obj.setAttr(_U(value), d );
0171 obj.setAttr(_U(unit), "g/cm3");
0172 obj.setAttr(_U(type), "density");
0173
0174 geo.checkMaterial(name, medium);
0175
0176 if (geo_mat->IsMixture()) {
0177 TGeoMixture *mix = (TGeoMixture*)geo_mat;
0178 const double *wmix = mix->GetWmixt();
0179 const int *nmix = mix->GetNmixt();
0180 double sum = 0e0;
0181 for (int i = 0, n = mix->GetNelements(); i < n; i++) {
0182 TGeoElement *elt = mix->GetElement(i);
0183 handleElement(elt->GetName(), Atom(elt));
0184 sum += wmix[i];
0185 }
0186 for (int i = 0, n = mix->GetNelements(); i < n; i++) {
0187 TGeoElement *elt = mix->GetElement(i);
0188
0189 if (nmix) {
0190 mat.append(obj = xml_elt_t(geo.doc, _U(composite)));
0191 obj.setAttr(_U(n), nmix[i]);
0192 }
0193 else {
0194 mat.append(obj = xml_elt_t(geo.doc, _U(fraction)));
0195 obj.setAttr(_U(n), wmix[i] / sum);
0196 }
0197 obj.setAttr(_U(ref), elt->GetName());
0198 }
0199 }
0200 else if ( name != "dummy" ) {
0201
0202
0203 TGeoElement *elt = geo_mat->GetElement(0);
0204 printout(INFO,"++ Converting non mixing material: %s",name.c_str());
0205 xml_elt_t atom(geo.doc, _U(atom));
0206 handleElement(elt->GetName(), Atom(elt));
0207 mat.append(atom);
0208 mat.setAttr(_U(Z), geo_mat->GetZ());
0209 atom.setAttr(_U(type), "A");
0210 atom.setAttr(_U(unit), "g/mol");
0211 atom.setAttr(_U(value), geo_mat->GetA() );
0212 }
0213 geo.doc_materials.append(mat);
0214 geo.xmlMaterials[medium] = mat;
0215 }
0216 return mat;
0217 }
0218
0219
0220 xml_h LCDDConverter::handleSolid(const std::string& name, const TGeoShape* shape) const {
0221 GeometryInfo& geo = data();
0222 SolidMap::iterator sit = geo.xmlSolids.find(shape);
0223 if (!shape) {
0224
0225
0226 return xml_h(0);
0227 }
0228 else if (sit != geo.xmlSolids.end()) {
0229
0230 return (*sit).second;
0231 }
0232 else if (shape->IsA() == TGeoShapeAssembly::Class()) {
0233
0234 return xml_h(0);
0235 }
0236 else {
0237 xml_h solid(0);
0238 xml_h zplane(0);
0239 TClass* isa = shape->IsA();
0240 std::string shape_name = shape->GetName();
0241 geo.checkShape(name, shape);
0242 if (isa == TGeoBBox::Class()) {
0243 const TGeoBBox* sh = (const TGeoBBox*) shape;
0244 geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(box)));
0245 solid.setAttr(_U(name), Unicode(shape_name));
0246 solid.setAttr(_U(x), 2 * sh->GetDX());
0247 solid.setAttr(_U(y), 2 * sh->GetDY());
0248 solid.setAttr(_U(z), 2 * sh->GetDZ());
0249 solid.setAttr(_U(lunit), "cm");
0250 }
0251 else if (isa == TGeoTube::Class()) {
0252 const TGeoTube* sh = (const TGeoTube*) shape;
0253 geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(tube)));
0254 solid.setAttr(_U(name), Unicode(shape_name));
0255 solid.setAttr(_U(rmin), sh->GetRmin());
0256 solid.setAttr(_U(rmax), sh->GetRmax());
0257 solid.setAttr(_U(z), 2 * sh->GetDz());
0258 solid.setAttr(_U(startphi), 0e0);
0259 solid.setAttr(_U(deltaphi), 360.0);
0260 solid.setAttr(_U(aunit), "deg");
0261 solid.setAttr(_U(lunit), "cm");
0262 }
0263 else if (isa == TGeoTubeSeg::Class()) {
0264 const TGeoTubeSeg* sh = (const TGeoTubeSeg*) shape;
0265 geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(tube)));
0266 solid.setAttr(_U(name), Unicode(shape_name));
0267 solid.setAttr(_U(rmin), sh->GetRmin());
0268 solid.setAttr(_U(rmax), sh->GetRmax());
0269 solid.setAttr(_U(z), 2 * sh->GetDz());
0270 solid.setAttr(_U(startphi), sh->GetPhi1());
0271 solid.setAttr(_U(deltaphi), sh->GetPhi2());
0272 solid.setAttr(_U(aunit), "deg");
0273 solid.setAttr(_U(lunit), "cm");
0274 }
0275 else if (isa == TGeoEltu::Class()) {
0276 const TGeoEltu* sh = (const TGeoEltu*) shape;
0277 geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(eltube)));
0278 solid.setAttr(_U(name), Unicode(shape_name));
0279 solid.setAttr(_U(dx), sh->GetA());
0280 solid.setAttr(_U(dy), sh->GetB());
0281 solid.setAttr(_U(dz), sh->GetDz());
0282 solid.setAttr(_U(lunit), "cm");
0283 }
0284 else if (isa == TGeoTrd1::Class()) {
0285 const TGeoTrd1* sh = (const TGeoTrd1*) shape;
0286 geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(trd)));
0287 solid.setAttr(_U(name), Unicode(shape_name));
0288 solid.setAttr(_U(x1), 2 * sh->GetDx1());
0289 solid.setAttr(_U(x2), 2 * sh->GetDx2());
0290 solid.setAttr(_U(y1), 2 * sh->GetDy());
0291 solid.setAttr(_U(y2), 2 * sh->GetDy());
0292 solid.setAttr(_U(z), 2 * sh->GetDz());
0293 solid.setAttr(_U(lunit), "cm");
0294 }
0295 else if (isa == TGeoTrd2::Class()) {
0296 const TGeoTrd2* sh = (const TGeoTrd2*) shape;
0297 geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(trd)));
0298 solid.setAttr(_U(name), Unicode(shape_name));
0299 solid.setAttr(_U(x1), 2 * sh->GetDx1());
0300 solid.setAttr(_U(x2), 2 * sh->GetDx2());
0301 solid.setAttr(_U(y1), 2 * sh->GetDy1());
0302 solid.setAttr(_U(y2), 2 * sh->GetDy2());
0303 solid.setAttr(_U(z), 2 * sh->GetDz());
0304 solid.setAttr(_U(lunit), "cm");
0305 }
0306 else if (isa == TGeoHype::Class()) {
0307 const TGeoHype* sh = (const TGeoHype*) shape;
0308 geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(hype)));
0309 solid.setAttr(_U(name), Unicode(shape_name));
0310 solid.setAttr(_U(rmin), sh->GetRmin());
0311 solid.setAttr(_U(rmax), sh->GetRmax());
0312 solid.setAttr(Unicode("inst"), sh->GetStIn());
0313 solid.setAttr(_U(outst), sh->GetStOut());
0314 solid.setAttr(_U(z), sh->GetDz());
0315 solid.setAttr(_U(aunit), "deg");
0316 solid.setAttr(_U(lunit), "cm");
0317 }
0318 else if (isa == TGeoPgon::Class()) {
0319 const TGeoPgon* sh = (const TGeoPgon*) shape;
0320 geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(polyhedra)));
0321 solid.setAttr(_U(name), Unicode(shape_name));
0322 solid.setAttr(_U(startphi), sh->GetPhi1());
0323 solid.setAttr(_U(deltaphi), sh->GetDphi());
0324 solid.setAttr(_U(numsides), sh->GetNedges());
0325 solid.setAttr(_U(aunit), "deg");
0326 solid.setAttr(_U(lunit), "cm");
0327 for (Int_t i = 0; i < sh->GetNz(); ++i) {
0328 zplane = xml_elt_t(geo.doc, _U(zplane));
0329 zplane.setAttr(_U(z), sh->GetZ(i));
0330 zplane.setAttr(_U(rmin), sh->GetRmin(i));
0331 zplane.setAttr(_U(rmax), sh->GetRmax(i));
0332 solid.append(zplane);
0333 }
0334 }
0335 else if (isa == TGeoPcon::Class()) {
0336 const TGeoPcon* sh = (const TGeoPcon*) shape;
0337 geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(polycone)));
0338 solid.setAttr(_U(name), Unicode(shape_name));
0339 solid.setAttr(_U(startphi), sh->GetPhi1());
0340 solid.setAttr(_U(deltaphi), sh->GetDphi());
0341 solid.setAttr(_U(aunit), "deg");
0342 solid.setAttr(_U(lunit), "cm");
0343 for (Int_t i = 0; i < sh->GetNz(); ++i) {
0344 zplane = xml_elt_t(geo.doc, _U(zplane));
0345 zplane.setAttr(_U(z), sh->GetZ(i));
0346 zplane.setAttr(_U(rmin), sh->GetRmin(i));
0347 zplane.setAttr(_U(rmax), sh->GetRmax(i));
0348 solid.append(zplane);
0349 }
0350 solid.setAttr(_U(lunit), "cm");
0351 }
0352 else if (isa == TGeoCone::Class()) {
0353 const TGeoCone* sh = (const TGeoCone*) shape;
0354 geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(cone)));
0355 solid.setAttr(_U(name), Unicode(shape_name));
0356 solid.setAttr(_U(z), 2 * sh->GetDz());
0357 solid.setAttr(_U(rmin1), sh->GetRmin1());
0358 solid.setAttr(_U(rmax1), sh->GetRmax1());
0359 solid.setAttr(_U(rmin2), sh->GetRmin2());
0360 solid.setAttr(_U(rmax2), sh->GetRmax2());
0361 solid.setAttr(_U(startphi), 0e0);
0362 solid.setAttr(_U(deltaphi), 360.0);
0363 solid.setAttr(_U(aunit), "deg");
0364 solid.setAttr(_U(lunit), "cm");
0365 }
0366 else if (isa == TGeoConeSeg::Class()) {
0367 const TGeoConeSeg* sh = (const TGeoConeSeg*) shape;
0368 geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(cone)));
0369 solid.setAttr(_U(name), Unicode(shape_name));
0370 solid.setAttr(_U(z), 2*sh->GetDz());
0371 solid.setAttr(_U(rmin1), sh->GetRmin1());
0372 solid.setAttr(_U(rmin2), sh->GetRmin2());
0373 solid.setAttr(_U(rmax1), sh->GetRmax1());
0374 solid.setAttr(_U(rmax2), sh->GetRmax2());
0375 solid.setAttr(_U(startphi), sh->GetPhi1());
0376 solid.setAttr(_U(deltaphi), sh->GetPhi2() - sh->GetPhi1());
0377 solid.setAttr(_U(aunit), "deg");
0378 solid.setAttr(_U(lunit), "cm");
0379 }
0380 else if (isa == TGeoParaboloid::Class()) {
0381 const TGeoParaboloid* sh = (const TGeoParaboloid*) shape;
0382 geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(paraboloid)));
0383 solid.setAttr(_U(name), Unicode(shape_name));
0384 solid.setAttr(_U(rlo), sh->GetRlo());
0385 solid.setAttr(_U(rhi), sh->GetRhi());
0386 solid.setAttr(_U(dz), sh->GetDz());
0387 solid.setAttr(_U(lunit), "cm");
0388 }
0389 #if 0
0390 else if (isa == TGeoEllipsoid::Class()) {
0391 const TGeoEllipsoid* sh = (const TGeoEllipsoid*) shape;
0392 geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(ellipsoid)));
0393 solid.setAttr(_U(lunit), "cm");
0394 }
0395 #endif
0396 else if (isa == TGeoSphere::Class()) {
0397 const TGeoSphere* sh = (const TGeoSphere*) shape;
0398 geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(sphere)));
0399 solid.setAttr(_U(name), Unicode(shape_name));
0400 solid.setAttr(_U(rmin), sh->GetRmin());
0401 solid.setAttr(_U(rmax), sh->GetRmax());
0402 solid.setAttr(_U(startphi), sh->GetPhi1());
0403 solid.setAttr(_U(deltaphi), (sh->GetPhi2() - sh->GetPhi1()));
0404 solid.setAttr(_U(starttheta), sh->GetTheta1());
0405 solid.setAttr(_U(deltatheta), (sh->GetTheta2() - sh->GetTheta1()));
0406 solid.setAttr(_U(aunit), "deg");
0407 solid.setAttr(_U(lunit), "cm");
0408 }
0409 else if (isa == TGeoTorus::Class()) {
0410 const TGeoTorus* sh = (const TGeoTorus*) shape;
0411 geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(torus)));
0412 solid.setAttr(_U(name), Unicode(shape_name));
0413 solid.setAttr(_U(rtor), sh->GetR());
0414 solid.setAttr(_U(rmin), sh->GetRmin());
0415 solid.setAttr(_U(rmax), sh->GetRmax());
0416 solid.setAttr(_U(startphi), sh->GetPhi1());
0417 solid.setAttr(_U(deltaphi), sh->GetDphi());
0418 solid.setAttr(_U(aunit), "deg");
0419 solid.setAttr(_U(lunit), "cm");
0420 }
0421 else if (isa == TGeoTrap::Class()) {
0422 const TGeoTrap* sh = (const TGeoTrap*) shape;
0423 geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(trap)));
0424 solid.setAttr(_U(name), Unicode(shape_name));
0425 solid.setAttr(_U(z), 2 * sh->GetDz());
0426 solid.setAttr(_U(x1), 2 * sh->GetBl1());
0427 solid.setAttr(_U(x2), 2 * sh->GetTl1());
0428 solid.setAttr(_U(x3), 2 * sh->GetBl2());
0429 solid.setAttr(_U(x4), 2 * sh->GetTl2());
0430 solid.setAttr(_U(y1), 2 * sh->GetH1());
0431 solid.setAttr(_U(y2), 2 * sh->GetH2());
0432 solid.setAttr(_U(alpha1), sh->GetAlpha1());
0433 solid.setAttr(_U(alpha2), sh->GetAlpha2());
0434 solid.setAttr(_U(theta), sh->GetTheta());
0435 solid.setAttr(_U(phi), sh->GetPhi());
0436 solid.setAttr(_U(aunit), "deg");
0437 solid.setAttr(_U(lunit), "cm");
0438 }
0439 else if (isa == TGeoPara::Class()) {
0440 const TGeoPara* sh = (const TGeoPara*) shape;
0441 geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(para)));
0442 solid.setAttr(_U(name), Unicode(shape_name));
0443 solid.setAttr(_U(x), sh->GetX());
0444 solid.setAttr(_U(y), sh->GetY());
0445 solid.setAttr(_U(z), sh->GetZ());
0446 solid.setAttr(_U(alpha), sh->GetAlpha());
0447 solid.setAttr(_U(theta), sh->GetTheta());
0448 solid.setAttr(_U(phi), sh->GetPhi());
0449 solid.setAttr(_U(aunit), "deg");
0450 solid.setAttr(_U(lunit), "cm");
0451 }
0452 else if (isa == TGeoArb8::Class()) {
0453 TGeoArb8* sh = (TGeoArb8*) shape;
0454 const double* vtx = sh->GetVertices();
0455 geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(arb8)));
0456 solid.setAttr(_U(name), Unicode(shape_name));
0457 solid.setAttr(_U(v1x), vtx[0]);
0458 solid.setAttr(_U(v1y), vtx[1]);
0459 solid.setAttr(_U(v2x), vtx[2]);
0460 solid.setAttr(_U(v2y), vtx[3]);
0461 solid.setAttr(_U(v3x), vtx[4]);
0462 solid.setAttr(_U(v3y), vtx[5]);
0463 solid.setAttr(_U(v4x), vtx[6]);
0464 solid.setAttr(_U(v4y), vtx[7]);
0465 solid.setAttr(_U(v5x), vtx[8]);
0466 solid.setAttr(_U(v5y), vtx[9]);
0467 solid.setAttr(_U(v6x), vtx[10]);
0468 solid.setAttr(_U(v6y), vtx[11]);
0469 solid.setAttr(_U(v7x), vtx[12]);
0470 solid.setAttr(_U(v7y), vtx[13]);
0471 solid.setAttr(_U(v8x), vtx[14]);
0472 solid.setAttr(_U(v8y), vtx[15]);
0473 solid.setAttr(_U(dz), sh->GetDz());
0474 solid.setAttr(_U(lunit), "cm");
0475 }
0476 else if (isa == TGeoScaledShape::Class()) {
0477 TGeoScaledShape* sh = (TGeoScaledShape*) shape;
0478 const double* vals = sh->GetScale()->GetScale();
0479 Solid s_sh(sh->GetShape());
0480 handleSolid(s_sh.name(), s_sh.ptr());
0481 geo.doc_solids.append(solid = xml_elt_t(geo.doc, _U(scale)));
0482 solid.setAttr(_U(name), Unicode(shape_name));
0483 solid.setAttr(_U(shape), s_sh.name());
0484 solid.setAttr(_U(x), vals[0]);
0485 solid.setAttr(_U(y), vals[1]);
0486 solid.setAttr(_U(z), vals[2]);
0487 solid.setAttr(_U(aunit), "deg");
0488 solid.setAttr(_U(lunit), "cm");
0489 }
0490 else if (isa == TGeoCompositeShape::Class() ||
0491 isa == TGeoUnion::Class() ||
0492 isa == TGeoIntersection::Class() ||
0493 isa == TGeoSubtraction::Class() ) {
0494 const TGeoCompositeShape* sh = (const TGeoCompositeShape*) shape;
0495 const TGeoBoolNode* boolean = sh->GetBoolNode();
0496 TGeoBoolNode::EGeoBoolType oper = boolean->GetBooleanOperator();
0497 TGeoMatrix* rm = boolean->GetRightMatrix();
0498 TGeoMatrix* lm = boolean->GetLeftMatrix();
0499 TGeoShape* ls = boolean->GetLeftShape();
0500 TGeoShape* rs = boolean->GetRightShape();
0501 xml_h left = handleSolid(ls->GetName(), ls);
0502 xml_h right = handleSolid(rs->GetName(), rs);
0503 xml_h first_solid(0), second_solid(0);
0504 if (!left) {
0505 throw std::runtime_error("G4Converter: No left Detector Solid present for composite shape:" + name);
0506 }
0507 if (!right) {
0508 throw std::runtime_error("G4Converter: No right Detector Solid present for composite shape:" + name);
0509 }
0510
0511
0512
0513
0514
0515 if (strcmp(ls->ClassName(), "TGeoScaledShape") == 0 &&
0516 strcmp(rs->ClassName(), "TGeoBBox") == 0) {
0517 if (strcmp(((TGeoScaledShape *)ls)->GetShape()->ClassName(), "TGeoSphere") == 0) {
0518 if (oper == TGeoBoolNode::kGeoIntersection) {
0519 TGeoScaledShape* lls = (TGeoScaledShape *)ls;
0520 TGeoBBox* rrs = (TGeoBBox*)rs;
0521 solid = xml_elt_t(geo.doc,Unicode("ellipsoid"));
0522 solid.setAttr(_U(name), Unicode(shape_name));
0523 double sx = lls->GetScale()->GetScale()[0];
0524 double sy = lls->GetScale()->GetScale()[1];
0525 double radius = ((TGeoSphere *)lls->GetShape())->GetRmax();
0526 double dz = rrs->GetDZ();
0527 double zorig = rrs->GetOrigin()[2];
0528 double zcut2 = dz + zorig;
0529 double zcut1 = 2 * zorig - zcut2;
0530 solid.setAttr(Unicode("ax"),sx * radius);
0531 solid.setAttr(Unicode("by"),sy * radius);
0532 solid.setAttr(Unicode("cz"),radius);
0533 solid.setAttr(Unicode("zcut1"),zcut1);
0534 solid.setAttr(Unicode("zcut2"),zcut2);
0535 solid.setAttr(_U(lunit), "cm");
0536 return data().xmlSolids[shape] = solid;
0537 }
0538 }
0539 }
0540
0541 if ( oper == TGeoBoolNode::kGeoSubtraction )
0542 solid = xml_elt_t(geo.doc,_U(subtraction));
0543 else if ( oper == TGeoBoolNode::kGeoUnion )
0544 solid = xml_elt_t(geo.doc,_U(union));
0545 else if ( oper == TGeoBoolNode::kGeoIntersection )
0546 solid = xml_elt_t(geo.doc,_U(intersection));
0547
0548 xml_h obj;
0549 std::string lnam = left.attr<std::string>(_U(name));
0550 std::string rnam = right.attr<std::string>(_U(name));
0551
0552 geo.doc_solids.append(solid);
0553 solid.append(first_solid = xml_elt_t(geo.doc, _U(first)));
0554 solid.setAttr(_U(name), Unicode(shape_name));
0555 first_solid.setAttr(_U(ref), lnam);
0556 const double *tr = lm->GetTranslation();
0557
0558 if ((tr[0] != 0.0) || (tr[1] != 0.0) || (tr[2] != 0.0)) {
0559 first_solid.append(obj = xml_elt_t(geo.doc, _U(firstposition)));
0560 obj.setAttr(_U(name), name+"_"+lnam+"_pos");
0561 obj.setAttr(_U(x), tr[0]);
0562 obj.setAttr(_U(y), tr[1]);
0563 obj.setAttr(_U(z), tr[2]);
0564 obj.setAttr(_U(unit), "cm");
0565 }
0566 if (lm->IsRotation()) {
0567 TGeoMatrix const & linv = lm->Inverse();
0568 XYZRotation rot = getXYZangles(linv.GetRotationMatrix());
0569 if ((rot.X() != 0.0) || (rot.Y() != 0.0) || (rot.Z() != 0.0)) {
0570 first_solid.append(obj = xml_elt_t(geo.doc, _U(firstrotation)));
0571 obj.setAttr(_U(name), name+"_"+lnam+"_rot");
0572 obj.setAttr(_U(x), rot.X());
0573 obj.setAttr(_U(y), rot.Y());
0574 obj.setAttr(_U(z), rot.Z());
0575 obj.setAttr(_U(unit), "rad");
0576 }
0577 }
0578 tr = rm->GetTranslation();
0579 solid.append(second_solid = xml_elt_t(geo.doc, _U(second)));
0580 second_solid.setAttr(_U(ref), rnam);
0581 if ((tr[0] != 0.0) || (tr[1] != 0.0) || (tr[2] != 0.0)) {
0582 xml_ref_t pos = handlePosition(rnam+"_pos", rm);
0583 solid.setRef(_U(positionref), pos.name());
0584 }
0585 if (rm->IsRotation()) {
0586 TGeoMatrix const & rinv = rm->Inverse();
0587 XYZRotation rot = getXYZangles(rinv.GetRotationMatrix());
0588 if ((rot.X() != 0.0) || (rot.Y() != 0.0) || (rot.Z() != 0.0)) {
0589 xml_ref_t xml_rot = handleRotation(rnam+"_rot", &rinv);
0590 solid.setRef(_U(rotationref), xml_rot.name());
0591 }
0592 }
0593 }
0594 if (!solid) {
0595 std::string err = "Failed to handle unknown solid shape:" + name + " of type " + std::string(shape->IsA()->GetName());
0596 throw std::runtime_error(err);
0597 }
0598 return data().xmlSolids[shape] = solid;
0599 }
0600 }
0601
0602
0603 xml_h LCDDConverter::handlePosition(const std::string& name, const TGeoMatrix* trafo) const {
0604 GeometryInfo& geo = data();
0605 xml_h pos = geo.xmlPositions[trafo];
0606 if (!pos) {
0607 const double* tr = trafo->GetTranslation();
0608 if (tr[0] != 0.0 || tr[1] != 0.0 || tr[2] != 0.0) {
0609 std::string gen_name = genName(name,trafo);
0610 geo.checkPosition(gen_name, trafo);
0611 geo.doc_define.append(pos = xml_elt_t(geo.doc, _U(position)));
0612 pos.setAttr(_U(name), gen_name);
0613 pos.setAttr(_U(x), tr[0]);
0614 pos.setAttr(_U(y), tr[1]);
0615 pos.setAttr(_U(z), tr[2]);
0616 pos.setAttr(_U(unit), "cm");
0617 }
0618 else if (geo.identity_pos) {
0619 pos = geo.identity_pos;
0620 }
0621 else {
0622 geo.doc_define.append(geo.identity_pos = xml_elt_t(geo.doc, _U(position)));
0623 geo.identity_pos.setAttr(_U(name), "identity_pos");
0624 geo.identity_pos.setAttr(_U(x), 0);
0625 geo.identity_pos.setAttr(_U(y), 0);
0626 geo.identity_pos.setAttr(_U(z), 0);
0627 geo.identity_pos.setAttr(_U(unit), "cm");
0628 pos = geo.identity_pos;
0629 geo.checkPosition("identity_pos", 0);
0630 }
0631 geo.xmlPositions[trafo] = pos;
0632 }
0633 return pos;
0634 }
0635
0636
0637 xml_h LCDDConverter::handleRotation(const std::string& name, const TGeoMatrix* trafo) const {
0638 GeometryInfo& geo = data();
0639 xml_h rot = geo.xmlRotations[trafo];
0640 if (!rot) {
0641 XYZRotation r = getXYZangles(trafo->GetRotationMatrix());
0642 if (!(r.X() == 0.0 && r.Y() == 0.0 && r.Z() == 0.0)) {
0643 std::string gen_name = genName(name,trafo);
0644 geo.checkRotation(gen_name, trafo);
0645 geo.doc_define.append(rot = xml_elt_t(geo.doc, _U(rotation)));
0646 rot.setAttr(_U(name), gen_name);
0647 rot.setAttr(_U(x), r.X());
0648 rot.setAttr(_U(y), r.Y());
0649 rot.setAttr(_U(z), r.Z());
0650 rot.setAttr(_U(unit), "rad");
0651 }
0652 else if (geo.identity_rot) {
0653 rot = geo.identity_rot;
0654 }
0655 else {
0656 geo.doc_define.append(geo.identity_rot = xml_elt_t(geo.doc, _U(rotation)));
0657 geo.identity_rot.setAttr(_U(name), "identity_rot");
0658 geo.identity_rot.setAttr(_U(x), 0);
0659 geo.identity_rot.setAttr(_U(y), 0);
0660 geo.identity_rot.setAttr(_U(z), 0);
0661 geo.identity_rot.setAttr(_U(unit), "rad");
0662 rot = geo.identity_rot;
0663 geo.checkRotation("identity_rot", 0);
0664 }
0665 geo.xmlRotations[trafo] = rot;
0666 }
0667 return rot;
0668 }
0669
0670
0671 xml_h LCDDConverter::handleVolume(const std::string& , Volume volume) const {
0672 GeometryInfo& geo = data();
0673 xml_h vol = geo.xmlVolumes[volume];
0674 if (!vol) {
0675 const TGeoVolume* v = volume;
0676 Volume _v(v);
0677 std::string n = genName(v->GetName(),v);
0678 TGeoMedium* medium = v->GetMedium();
0679 TGeoShape* sh = v->GetShape();
0680 xml_ref_t sol = handleSolid(sh->GetName(), sh);
0681
0682 geo.checkVolume(n, volume);
0683 if (v->IsAssembly()) {
0684 vol = xml_elt_t(geo.doc, _U(assembly));
0685 vol.setAttr(_U(name), n);
0686 }
0687 else {
0688 if (!sol)
0689 throw std::runtime_error("G4Converter: No Detector Solid present for volume:" + n);
0690 else if (!m)
0691 throw std::runtime_error("G4Converter: No Detector material present for volume:" + n);
0692
0693 vol = xml_elt_t(geo.doc, _U(volume));
0694 vol.setAttr(_U(name), n);
0695 if (m) {
0696 std::string mat_name = medium->GetName();
0697 xml_ref_t med = handleMaterial(mat_name, Material(medium));
0698 vol.setRef(_U(materialref), med.name());
0699 }
0700 vol.setRef(_U(solidref), sol.name());
0701 }
0702 geo.doc_structure.append(vol);
0703 geo.xmlVolumes[v] = vol;
0704 const TObjArray* dau = const_cast<TGeoVolume*>(v)->GetNodes();
0705 if (dau && dau->GetEntries() > 0) {
0706 for (Int_t i = 0, n_dau = dau->GetEntries(); i < n_dau; ++i) {
0707 TGeoNode* node = reinterpret_cast<TGeoNode*>(dau->At(i));
0708 handlePlacement(node->GetName(), node);
0709 }
0710 }
0711 if (geo.doc_header && is_volume(volume)) {
0712 Region reg = _v.region();
0713 LimitSet lim = _v.limitSet();
0714 VisAttr vis = _v.visAttributes();
0715 SensitiveDetector det = _v.sensitiveDetector();
0716 if (det.isValid()) {
0717 xml_ref_t xml_data = handleSensitive(det.name(), det);
0718 vol.setRef(_U(sdref), xml_data.name());
0719 }
0720 if (reg.isValid()) {
0721 xml_ref_t xml_data = handleRegion(reg.name(), reg);
0722 vol.setRef(_U(regionref), xml_data.name());
0723 }
0724 if (lim.isValid()) {
0725 xml_ref_t xml_data = handleLimitSet(lim.name(), lim);
0726 vol.setRef(_U(limitsetref), xml_data.name());
0727 }
0728 if (vis.isValid()) {
0729 xml_ref_t xml_data = handleVis(vis.name(), vis);
0730 vol.setRef(_U(visref), xml_data.name());
0731 }
0732 }
0733 }
0734 return vol;
0735 }
0736
0737
0738 xml_h LCDDConverter::handleVolumeVis(const std::string& , const TGeoVolume* volume) const {
0739 GeometryInfo& geo = data();
0740 xml_h vol = geo.xmlVolumes[volume];
0741 if (!vol) {
0742 const TGeoVolume* v = volume;
0743 Volume _v(volume);
0744 if (is_volume(volume)) {
0745 VisAttr vis = _v.visAttributes();
0746 if (vis.isValid()) {
0747 geo.doc_structure.append(vol = xml_elt_t(geo.doc, _U(volume)));
0748 vol.setAttr(_U(name), v->GetName());
0749 xml_ref_t xml_data = handleVis(vis.name(), vis);
0750 vol.setRef(_U(visref), xml_data.name());
0751 geo.xmlVolumes[v] = vol;
0752 }
0753 }
0754 }
0755 return vol;
0756 }
0757
0758
0759 void LCDDConverter::collectVolume(const std::string& , const TGeoVolume* volume) const {
0760 Volume v(volume);
0761 if ( is_volume(volume) ) {
0762 GeometryInfo& geo = data();
0763 Region reg = v.region();
0764 LimitSet lim = v.limitSet();
0765 SensitiveDetector det = v.sensitiveDetector();
0766 if (lim.isValid())
0767 geo.limits.insert(lim);
0768 if (reg.isValid())
0769 geo.regions.insert(reg);
0770 if (det.isValid())
0771 geo.sensitives.insert(det);
0772 }
0773 else {
0774 printout(WARNING,"LCDDConverter","++ CollectVolume: Skip volume: %s",volume->GetName());
0775 }
0776 }
0777
0778 void LCDDConverter::checkVolumes(const std::string& , Volume v) const {
0779 std::string n = v.name()+_toString(v.ptr(),"_%p");
0780 NameSet::const_iterator i = m_checkNames.find(n);
0781 if (i != m_checkNames.end()) {
0782 std::stringstream str;
0783 str << "++ CheckVolumes: Volume " << n << " ";
0784 if (is_volume(v.ptr())) {
0785 SensitiveDetector sd = v.sensitiveDetector();
0786 VisAttr vis = v.visAttributes();
0787 if (sd.isValid()) {
0788 str << "of " << sd.name() << " ";
0789 }
0790 else if (vis.isValid()) {
0791 str << "with VisAttrs " << vis.name() << " ";
0792 }
0793 }
0794 str << "has duplicate entries." << std::endl;
0795 printout(ERROR,"LCDDConverter",str.str().c_str());
0796 return;
0797 }
0798 m_checkNames.insert(n);
0799 }
0800
0801
0802 xml_h LCDDConverter::handlePlacement(const std::string& name,PlacedVolume node) const {
0803 GeometryInfo& geo = data();
0804 xml_h place = geo.xmlPlacements[node];
0805 if (!place) {
0806 TGeoMatrix* matrix = node->GetMatrix();
0807 TGeoVolume* volume = node->GetVolume();
0808 xml_ref_t vol = xml_h(geo.xmlVolumes[volume]);
0809 xml_h mot = geo.xmlVolumes[node->GetMotherVolume()];
0810
0811 place = xml_elt_t(geo.doc, _U(physvol));
0812 if (mot) {
0813 mot.append(place);
0814 }
0815 place.setRef(_U(volumeref), vol.name());
0816 if (m) {
0817 xml_ref_t pos = handlePosition(name+"_pos", matrix);
0818 place.setRef(_U(positionref), pos.name());
0819 if ( matrix->IsRotation() ) {
0820 xml_ref_t rot = handleRotation(name+"_rot", matrix);
0821 place.setRef(_U(rotationref), rot.name());
0822 }
0823 }
0824 if (geo.doc_root.tag() != "gdml") {
0825 if (is_placement(node)) {
0826 const PlacedVolume::VolIDs& ids = node.volIDs();
0827 for (PlacedVolume::VolIDs::const_iterator i = ids.begin(); i != ids.end(); ++i) {
0828 xml_h pvid = xml_elt_t(geo.doc, _U(physvolid));
0829 pvid.setAttr(_U(field_name), (*i).first);
0830 pvid.setAttr(_U(value), (*i).second);
0831 place.append(pvid);
0832 }
0833 }
0834 }
0835 geo.xmlPlacements[node] = place;
0836 }
0837 else {
0838 std::cout << "Attempt to DOUBLE-place physical volume:" << name << " No:" << node->GetNumber() << std::endl;
0839 }
0840 return place;
0841 }
0842
0843
0844 xml_h LCDDConverter::handleRegion(const std::string& , Region region) const {
0845 GeometryInfo& geo = data();
0846 xml_h reg = geo.xmlRegions[region];
0847 if (!reg) {
0848 geo.doc_regions.append(reg = xml_elt_t(geo.doc, _U(region)));
0849 reg.setAttr(_U(name), region.name());
0850 reg.setAttr(_U(cut), region.cut());
0851 reg.setAttr(_U(eunit), "GeV");
0852 reg.setAttr(_U(lunit), "cm");
0853 reg.setAttr(_U(store_secondaries), region.storeSecondaries());
0854 geo.xmlRegions[region] = reg;
0855 }
0856 return reg;
0857 }
0858
0859
0860 xml_h LCDDConverter::handleLimitSet(const std::string& , LimitSet lim) const {
0861 GeometryInfo& geo = data();
0862 xml_h xml = geo.xmlLimits[lim];
0863 if (!xml) {
0864 geo.doc_limits.append(xml = xml_elt_t(geo.doc, _U(limitset)));
0865 xml.setAttr(_U(name), lim.name());
0866 const std::set<Limit>& obj = lim.limits();
0867 for (std::set<Limit>::const_iterator i = obj.begin(); i != obj.end(); ++i) {
0868 xml_h x = xml_elt_t(geo.doc, _U(limit));
0869 const Limit& l = *i;
0870 xml.append(x);
0871 x.setAttr(_U(name), l.name);
0872 x.setAttr(_U(unit), l.unit);
0873 x.setAttr(_U(value), l.value);
0874 x.setAttr(_U(particles), l.particles);
0875 }
0876 geo.xmlLimits[lim] = xml;
0877 }
0878 return xml;
0879 }
0880
0881
0882 xml_h LCDDConverter::handleSegmentation(Segmentation seg) const {
0883 xml_h xml;
0884 if (seg.isValid()) {
0885 typedef DDSegmentation::Parameters _P;
0886 std::string typ = seg.type();
0887 _P p = seg.parameters();
0888 xml = xml_elt_t(data().doc, Unicode(typ));
0889 for (_P::const_iterator i = p.begin(); i != p.end(); ++i) {
0890 const _P::value_type& v = *i;
0891 if (v->name() == "lunit") {
0892 std::string val = v->value() == _toDouble("mm") ? "mm" : v->value() == _toDouble("cm") ? "cm" :
0893 v->value() == _toDouble("m") ? "m" : v->value() == _toDouble("micron") ? "micron" :
0894 v->value() == _toDouble("nanometer") ? "namometer" : "??";
0895 xml.setAttr(Unicode(v->name()), Unicode(val));
0896 continue;
0897 }
0898
0899 if (v->unitType() == DDSegmentation::SegmentationParameter::LengthUnit) {
0900 double value = _toDouble(v->value()) / dd4hep::mm;
0901 xml.setAttr(Unicode(v->name()), value);
0902 } else if (v->unitType() == DDSegmentation::SegmentationParameter::AngleUnit) {
0903 double value = _toDouble(v->value()) * DEGREE_2_RAD;
0904 xml.setAttr(Unicode(v->name()), value);
0905 } else {
0906 xml.setAttr(Unicode(v->name()), v->value());
0907 }
0908 }
0909 }
0910 return xml;
0911 }
0912
0913
0914 xml_h LCDDConverter::handleSensitive(const std::string& , SensitiveDetector sd) const {
0915 GeometryInfo& geo = data();
0916 xml_h sensdet = geo.xmlSensDets[sd];
0917 if (!sensdet) {
0918 geo.doc_detectors.append(sensdet = xml_elt_t(geo.doc, Unicode(sd.type())));
0919 sensdet.setAttr(_U(name), sd.name());
0920 sensdet.setAttr(_U(ecut), sd.energyCutoff());
0921 sensdet.setAttr(_U(eunit), "MeV");
0922 sensdet.setAttr(_U(verbose), int(sd.verbose() ? 1 : 0));
0923 sensdet.setAttr(_U(hits_collection), sd.hitsCollection());
0924 if (sd.combineHits())
0925 sensdet.setAttr(_U(combine_hits), sd.combineHits());
0926 Readout ro = sd.readout();
0927 if (ro.isValid()) {
0928 xml_ref_t ref = handleIdSpec(ro.idSpec().name(), ro.idSpec());
0929 sensdet.setRef(_U(idspecref), ref.name());
0930 xml_h seg = handleSegmentation(ro.segmentation());
0931 if (seg)
0932 sensdet.append(seg);
0933 }
0934 geo.xmlSensDets[sd] = sensdet;
0935 }
0936 return sensdet;
0937 }
0938
0939
0940 xml_h LCDDConverter::handleIdSpec(const std::string& name, IDDescriptor id_spec) const {
0941 GeometryInfo& geo = data();
0942 xml_h id = geo.xmlIdSpecs[id_spec];
0943 if (!id) {
0944 int length = 0, start = 0;
0945 IDDescriptor desc = id_spec;
0946 geo.doc_idDict.append(id = xml_elt_t(geo.doc, _U(idspec)));
0947 id.setAttr(_U(name), name);
0948 const IDDescriptor::FieldMap& fm = desc.fields();
0949 for (const auto& i : fm ) {
0950 xml_h idfield = xml_elt_t(geo.doc, _U(idfield));
0951 #if 0
0952 const BitFieldElement* f = i.second;
0953 start = f.first;
0954 length = f.second<0 ? -f.second : f.second;
0955 idfield.setAttr(_U(signed),f.second<0 ? true : false);
0956 idfield.setAttr(_U(label),(*i).first);
0957 idfield.setAttr(_U(length),length);
0958 idfield.setAttr(_U(start),start);
0959 #else
0960 const BitFieldElement* f = i.second;
0961 idfield.setAttr(_U(signed),f->isSigned() ? true : false);
0962 idfield.setAttr(_U(label), f->name());
0963 idfield.setAttr(_U(length), (int) f->width());
0964 idfield.setAttr(_U(start), (int) f->offset());
0965 #endif
0966 id.append(idfield);
0967 }
0968 id.setAttr(_U(length), length + start);
0969 geo.xmlIdSpecs[id_spec] = id;
0970 }
0971 return id;
0972 }
0973
0974
0975 xml_h LCDDConverter::handleVis(const std::string& , VisAttr attr) const {
0976 GeometryInfo& geo = data();
0977 xml_h vis = geo.xmlVis[attr];
0978 if (!vis) {
0979 float red = 0, green = 0, blue = 0;
0980 int style = attr.lineStyle();
0981 int draw = attr.drawingStyle();
0982
0983 geo.doc_display.append(vis = xml_elt_t(geo.doc, _U(vis)));
0984 vis.setAttr(_U(name), attr.name());
0985 vis.setAttr(_U(visible), attr.visible());
0986 vis.setAttr(_U(show_daughters), attr.showDaughters());
0987 if (style == VisAttr::SOLID)
0988 vis.setAttr(_U(line_style), "unbroken");
0989 else if (style == VisAttr::DASHED)
0990 vis.setAttr(_U(line_style), "broken");
0991 if (draw == VisAttr::SOLID)
0992 vis.setAttr(_U(drawing_style), "solid");
0993 else if (draw == VisAttr::WIREFRAME)
0994 vis.setAttr(_U(drawing_style), "wireframe");
0995
0996 xml_h col = xml_elt_t(geo.doc, _U(color));
0997 attr.rgb(red, green, blue);
0998 col.setAttr(_U(alpha), attr.alpha());
0999 col.setAttr(_U(R), red);
1000 col.setAttr(_U(B), blue);
1001 col.setAttr(_U(G), green);
1002 vis.append(col);
1003 geo.xmlVis[attr] = vis;
1004 }
1005 return vis;
1006 }
1007
1008
1009 xml_h LCDDConverter::handleField(const std::string& , OverlayedField f) const {
1010 GeometryInfo& geo = data();
1011 xml_h field = geo.xmlFields[f];
1012 if (!field) {
1013 Handle<NamedObject> fld(f);
1014 std::string type = f->GetTitle();
1015 field = xml_elt_t(geo.doc, Unicode(type));
1016 field.setAttr(_U(name), f->GetName());
1017 fld = PluginService::Create<NamedObject*>(type + "_Convert2Detector", &m_detDesc, &field, &fld);
1018 printout(ALWAYS,"LCDDConverter","++ %s electromagnetic field:%s of type %s",
1019 (fld.isValid() ? "Converted" : "FAILED to convert "), f->GetName(), type.c_str());
1020 if (!fld.isValid()) {
1021 PluginDebug dbg;
1022 PluginService::Create<NamedObject*>(type + "_Convert2Detector", &m_detDesc, &field, &fld);
1023 except("LCDDConverter", "Failed to locate plugin to convert electromagnetic field:"
1024 + std::string(f->GetName()) + " of type " + type + ". "
1025 + dbg.missingFactory(type));
1026 }
1027 geo.doc_fields.append(field);
1028 }
1029 return field;
1030 }
1031
1032
1033 void LCDDConverter::handleProperties(Detector::Properties& prp) const {
1034 std::map<std::string, std::string> processors;
1035 static int s_idd = 9999999;
1036 std::string id;
1037 for (Detector::Properties::const_iterator i = prp.begin(); i != prp.end(); ++i) {
1038 const std::string& nam = (*i).first;
1039 const Detector::PropertyValues& vals = (*i).second;
1040 if (nam.substr(0, 6) == "geant4") {
1041 Detector::PropertyValues::const_iterator id_it = vals.find("id");
1042 if (id_it != vals.end()) {
1043 id = (*id_it).second;
1044 }
1045 else {
1046 char text[32];
1047 ::snprintf(text, sizeof(text), "%d", ++s_idd);
1048 id = text;
1049 }
1050 processors.insert(make_pair(id, nam));
1051 }
1052 }
1053 for (std::map<std::string, std::string>::const_iterator i = processors.begin(); i != processors.end(); ++i) {
1054 const GeoHandler* ptr = this;
1055 std::string nam = (*i).second;
1056 const Detector::PropertyValues& vals = prp[nam];
1057 auto iter = vals.find("type");
1058 if ( iter != vals.end() ) {
1059 std::string type = iter->second;
1060 std::string tag = type + "_Geant4_action";
1061 long result = PluginService::Create<long>(tag, &m_detDesc, ptr, &vals);
1062 if (0 == result) {
1063 PluginDebug dbg;
1064 result = PluginService::Create<long>(tag, &m_detDesc, ptr, &vals);
1065 if (0 == result) {
1066 except("LCDDConverter", "Failed to locate plugin to interprete files of type"
1067 " \"" + tag + "\" - no factory:" + type + ". " +
1068 dbg.missingFactory(tag));
1069 }
1070 }
1071 result = *(long*) result;
1072 if (result != 1) {
1073 except("LCDDConverter", "Failed to invoke the plugin " + tag + " of type " + type);
1074 }
1075 printout(INFO,"","+++ Executed Successfully Detector setup module %s.", type.c_str());
1076 continue;
1077 }
1078 printout(INFO,"","+++ FAILED to execute Detector setup module %s.", nam.c_str());
1079 }
1080 }
1081
1082
1083 void LCDDConverter::handleHeader() const {
1084 GeometryInfo& geo = data();
1085 Header hdr = m_detDesc.header();
1086 if ( hdr.isValid() ) {
1087 xml_h obj;
1088 geo.doc_header.append(obj = xml_elt_t(geo.doc, _U(detector)));
1089 obj.setAttr(_U(name), hdr.name());
1090 geo.doc_header.append(obj = xml_elt_t(geo.doc, _U(generator)));
1091 obj.setAttr(_U(name), "LCDDConverter");
1092 obj.setAttr(_U(version), hdr.version());
1093 obj.setAttr(_U(file), hdr.url());
1094 obj.setAttr(_U(checksum), Unicode(m_detDesc.constantAsString("compact_checksum")));
1095 geo.doc_header.append(obj = xml_elt_t(geo.doc, _U(author)));
1096 obj.setAttr(_U(name), hdr.author());
1097 geo.doc_header.append(obj = xml_elt_t(geo.doc, _U(comment)));
1098 obj.setText(hdr.comment());
1099 return;
1100 }
1101 printout(WARNING,"LCDDConverter","+++ No Detector header information availible from the geometry description.");
1102 }
1103
1104 template <typename O, typename C, typename F> void handle(const O* o, const C& c, F pmf) {
1105 for (typename C::const_iterator i = c.begin(); i != c.end(); ++i) {
1106 std::string n = (*i)->GetName();
1107 (o->*pmf)(n, *i);
1108 }
1109 }
1110
1111 template <typename O, typename C, typename F> void handleMap(const O* o, const C& c, F pmf) {
1112 for (typename C::const_iterator i = c.begin(); i != c.end(); ++i)
1113 (o->*pmf)((*i).first, (*i).second);
1114 }
1115
1116 template <typename O, typename C, typename F> void handleRMap(const O* o, const C& c, F pmf) {
1117 for (typename C::const_reverse_iterator i = c.rbegin(); i != c.rend(); ++i)
1118 handle(o, (*i).second, pmf);
1119 }
1120
1121
1122 xml_doc_t LCDDConverter::createGDML(DetElement top) {
1123 Detector& description = m_detDesc;
1124 if (!top.isValid()) {
1125 throw std::runtime_error("Attempt to call createGDML with an invalid geometry!");
1126 }
1127 GeometryInfo& geo = *(m_dataPtr = new GeometryInfo);
1128 m_data->clear();
1129 collect(top, geo);
1130
1131 printout(ALWAYS,"LCDDConverter","++ ==> Converting in memory detector description to GDML format...");
1132 xml::DocumentHandler docH;
1133 geo.doc = docH.create("gdml", docH.defaultComment());
1134 geo.doc_root = geo.doc.root();
1135 geo.doc_root.setAttr(Unicode("xmlns:xs"), "http://www.w3.org/2001/XMLSchema-instance");
1136 geo.doc_root.setAttr(Unicode("xs:noNamespaceSchemaLocation"),
1137 "http://service-spi.web.cern.ch/service-spi/app/releases/GDML/schema/gdml.xsd");
1138
1139
1140
1141
1142 Volume world_vol = description.worldVolume();
1143 geo.doc_root.append(geo.doc_define = xml_elt_t(geo.doc, _U(define)));
1144 geo.doc_root.append(geo.doc_materials = xml_elt_t(geo.doc, _U(materials)));
1145 geo.doc_root.append(geo.doc_solids = xml_elt_t(geo.doc, _U(solids)));
1146 geo.doc_root.append(geo.doc_structure = xml_elt_t(geo.doc, _U(structure)));
1147 geo.doc_root.append(geo.doc_setup = xml_elt_t(geo.doc, _U(setup)));
1148 geo.doc_setup.setRef(_U(world), genName(world_vol.name(),world_vol.ptr()));
1149 geo.doc_setup.setAttr(_U(name), Unicode("default"));
1150 geo.doc_setup.setAttr(_U(version), Unicode("1.0"));
1151
1152
1153 #if 0
1154 const Detector::HandleMap& mat = description.materials();
1155 for(Detector::HandleMap::const_iterator i=mat.begin(); i!=mat.end(); ++i)
1156 geo.materials.insert(dynamic_cast<TGeoMedium*>((*i).second.ptr()));
1157 #endif
1158
1159
1160 handle(this, geo.materials, &LCDDConverter::handleMaterial);
1161 printout(ALWAYS,"LCDDConverter","++ Handled %ld materials.",geo.materials.size());
1162
1163 handle(this, geo.volumes, &LCDDConverter::collectVolume);
1164 printout(ALWAYS,"LCDDConverter","++ Collected %ld volumes.",geo.volumes.size());
1165
1166 handle(this, geo.solids, &LCDDConverter::handleSolid);
1167 printout(ALWAYS,"LCDDConverter","++ Handled %ld solids.",geo.solids.size());
1168
1169 handle(this, geo.volumes, &LCDDConverter::handleVolume);
1170 printout(ALWAYS,"LCDDConverter","++ Handled %ld volumes.",geo.volumes.size());
1171
1172 m_checkNames.clear();
1173 handle(this, geo.volumes, &LCDDConverter::checkVolumes);
1174 return geo.doc;
1175 }
1176
1177
1178 xml_doc_t LCDDConverter::createVis(DetElement top) {
1179 if (!top.isValid()) {
1180 throw std::runtime_error("Attempt to call createDetector with an invalid geometry!");
1181 }
1182
1183 GeometryInfo& geo = *(m_dataPtr = new GeometryInfo);
1184 m_data->clear();
1185 collect(top, geo);
1186 printout(ALWAYS,"LCDDConverter","++ ==> Dump visualisation attributes "
1187 "from in memory detector description...");
1188 xml::DocumentHandler docH;
1189 xml_elt_t elt(0);
1190 geo.doc = docH.create("visualization", docH.defaultComment());
1191 geo.doc_root = geo.doc.root();
1192 geo.doc_root.append(geo.doc_display = xml_elt_t(geo.doc, _U(display)));
1193 geo.doc_root.append(geo.doc_structure = xml_elt_t(geo.doc, _U(structure)));
1194
1195 handle(this, geo.volumes, &LCDDConverter::collectVolume);
1196 handle(this, geo.volumes, &LCDDConverter::handleVolumeVis);
1197 printout(ALWAYS,"LCDDConverter","++ Handled %ld volumes.",geo.volumes.size());
1198 return geo.doc;
1199 }
1200
1201
1202 xml_doc_t LCDDConverter::createDetector(DetElement top) {
1203 Detector& description = m_detDesc;
1204 if (!top.isValid()) {
1205 throw std::runtime_error("Attempt to call createDetector with an invalid geometry!");
1206 }
1207
1208 GeometryInfo& geo = *(m_dataPtr = new GeometryInfo);
1209 m_data->clear();
1210 collect(top, geo);
1211 xml::DocumentHandler docH;
1212 xml_elt_t elt(0);
1213 Volume world_vol = description.worldVolume();
1214 geo.doc = docH.create("description", docH.defaultComment());
1215 geo.doc_root = geo.doc.root();
1216 geo.doc_root.setAttr(Unicode("xmlns:description"), "http://www.lcsim.org/schemas/description/1.0");
1217 geo.doc_root.setAttr(Unicode("xmlns:xs"), "http://www.w3.org/2001/XMLSchema-instance");
1218 geo.doc_root.setAttr(Unicode("xs:noNamespaceSchemaLocation"),
1219 "http://www.lcsim.org/schemas/description/1.0/description.xsd");
1220
1221 geo.doc_root.append(geo.doc_header = xml_elt_t(geo.doc, _U(header)));
1222 geo.doc_root.append(geo.doc_idDict = xml_elt_t(geo.doc, _U(iddict)));
1223 geo.doc_root.append(geo.doc_detectors = xml_elt_t(geo.doc, _U(sensitive_detectors)));
1224 geo.doc_root.append(geo.doc_limits = xml_elt_t(geo.doc, _U(limits)));
1225 geo.doc_root.append(geo.doc_regions = xml_elt_t(geo.doc, _U(regions)));
1226 geo.doc_root.append(geo.doc_display = xml_elt_t(geo.doc, _U(display)));
1227 geo.doc_root.append(geo.doc_gdml = xml_elt_t(geo.doc, _U(gdml)));
1228 geo.doc_root.append(geo.doc_fields = xml_elt_t(geo.doc, _U(fields)));
1229
1230 geo.doc_gdml.append(geo.doc_define = xml_elt_t(geo.doc, _U(define)));
1231 geo.doc_gdml.append(geo.doc_materials = xml_elt_t(geo.doc, _U(materials)));
1232 geo.doc_gdml.append(geo.doc_solids = xml_elt_t(geo.doc, _U(solids)));
1233 geo.doc_gdml.append(geo.doc_structure = xml_elt_t(geo.doc, _U(structure)));
1234 geo.doc_gdml.append(geo.doc_setup = xml_elt_t(geo.doc, _U(setup)));
1235 geo.doc_setup.setRef(_U(world), genName(world_vol.name(),world_vol.ptr()));
1236 geo.doc_setup.setAttr(_U(name), Unicode("default"));
1237 geo.doc_setup.setAttr(_U(version), Unicode("1.0"));
1238
1239
1240 const Detector::HandleMap& fld = description.fields();
1241 for (Detector::HandleMap::const_iterator i = fld.begin(); i != fld.end(); ++i)
1242 geo.fields.insert((*i).second);
1243
1244 printout(ALWAYS,"LCDDConverter","++ ==> Converting in memory detector description to Detector format...");
1245 handleHeader();
1246
1247 handle(this, geo.materials, &LCDDConverter::handleMaterial);
1248 printout(ALWAYS,"LCDDConverter","++ Handled %ld materials.",geo.materials.size());
1249
1250 handle(this, geo.volumes, &LCDDConverter::collectVolume);
1251 printout(ALWAYS,"LCDDConverter","++ Collected %ld volumes.",geo.volumes.size());
1252
1253 handle(this, geo.solids, &LCDDConverter::handleSolid);
1254 printout(ALWAYS,"LCDDConverter","++ Handled %ld solids.",geo.solids.size());
1255
1256 handle(this, geo.vis, &LCDDConverter::handleVis);
1257 printout(ALWAYS,"LCDDConverter","++ Handled %ld visualization attributes.",geo.vis.size());
1258
1259 handle(this, geo.sensitives, &LCDDConverter::handleSensitive);
1260 printout(ALWAYS,"LCDDConverter","++ Handled %ld sensitive detectors.",geo.sensitives.size());
1261
1262 handle(this, geo.limits, &LCDDConverter::handleLimitSet);
1263 printout(ALWAYS,"LCDDConverter","++ Handled %ld limit sets.",geo.limits.size());
1264
1265 handle(this, geo.regions, &LCDDConverter::handleRegion);
1266 printout(ALWAYS,"LCDDConverter","++ Handled %ld regions.",geo.regions.size());
1267
1268 handle(this, geo.volumes, &LCDDConverter::handleVolume);
1269 printout(ALWAYS,"LCDDConverter","++ Handled %ld volumes.",geo.volumes.size());
1270
1271 handle(this, geo.fields, &LCDDConverter::handleField);
1272 printout(ALWAYS,"LCDDConverter","++ Handled %ld fields.",geo.fields.size());
1273
1274 m_checkNames.clear();
1275 handle(this, geo.volumes, &LCDDConverter::checkVolumes);
1276 #if 0
1277
1278 handleProperties(m_detDesc.properties());
1279 #endif
1280 return geo.doc;
1281 }
1282
1283
1284 LCDDConverter::GeometryInfo::GeometryInfo()
1285 : doc(0), doc_root(0), doc_header(0), doc_idDict(0), doc_detectors(0), doc_limits(0),
1286 doc_regions(0), doc_display(0), doc_gdml(0), doc_fields(0), doc_define(0),
1287 doc_materials(0), doc_solids(0), doc_structure(0), doc_setup(0)
1288 {
1289 }
1290
1291 static long dump_output(xml_doc_t doc, int argc, char** argv) {
1292 xml::DocumentHandler docH;
1293 return docH.output(doc, argc > 0 ? argv[0] : "");
1294 }
1295
1296 long create_gdml_from_dd4hep(Detector& description, int argc, char** argv) {
1297 LCDDConverter wr(description);
1298 return dump_output(wr.createGDML(description.world()), argc, argv);
1299 }
1300
1301 static long create_description(Detector& description, int argc, char** argv) {
1302 LCDDConverter wr(description);
1303 return dump_output(wr.createDetector(description.world()), argc, argv);
1304 }
1305
1306 static long create_vis(Detector& description, int argc, char** argv) {
1307 LCDDConverter wr(description);
1308 return dump_output(wr.createVis(description.world()), argc, argv);
1309 }
1310
1311 static long create_visASCII(Detector& description, int , char** argv) {
1312 LCDDConverter wr(description);
1313 wr.createVis(description.world());
1314 LCDDConverter::GeometryInfo& geo = wr.data();
1315 std::map<std::string, xml_comp_t> vis_map;
1316 for (xml_coll_t c(geo.doc_display, _U(vis)); c; ++c)
1317 vis_map.insert(make_pair(xml_comp_t(c).nameStr(), xml_comp_t(c)));
1318
1319 const char* sep = ";";
1320 std::ofstream os(argv[0]);
1321 for (xml_coll_t c(geo.doc_structure, _U(volume)); c; ++c) {
1322 xml_comp_t vol = c;
1323 xml_comp_t ref = c.child(_U(visref));
1324 auto iter = vis_map.find(ref.refStr());
1325 if ( iter != vis_map.end() ) {
1326 xml_comp_t vis = iter->second;
1327 xml_comp_t col = vis.child(_U(color));
1328 os << "vol:" << vol.nameStr() << sep << "vis:" << vis.nameStr() << sep
1329 << "visible:" << vis.visible() << sep << "r:"
1330 << col.R() << sep << "g:" << col.G() << sep << "b:" << col.B() << sep
1331 << "alpha:" << col.alpha() << sep << "line_style:"
1332 << vis.attr < std::string > (_U(line_style)) << sep
1333 << "drawing_style:" << vis.attr < std::string> (_U(drawing_style)) << sep
1334 << "show_daughters:" << vis.show_daughters() << sep << std::endl;
1335 }
1336 }
1337 os.close();
1338 return 1;
1339 }
1340
1341 DECLARE_APPLY(DD4hepGeometry2VIS, create_vis)
1342 DECLARE_APPLY(DD4hepGeometry2VISASCII, create_visASCII)
1343
1344 DECLARE_APPLY(DD4hepGeometry2Detector, create_description)