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