From f1adc5f5114fd2470ee6c270fed51f2db5cdaf26 Mon Sep 17 00:00:00 2001 From: Markus Frank <Markus.Frank@cern.ch> Date: Fri, 23 Oct 2020 14:33:19 +0200 Subject: [PATCH] Fix to the translation of reflected volumes --- DDCore/include/DD4hep/Volumes.h | 4 + DDCore/include/XML/UnicodeValues.h | 3 + DDCore/src/Volumes.cpp | 73 ++++++---- DDCore/src/plugins/ShapePlugins.cpp | 33 +++-- DDDetectors/src/ReflectedDetector_geo.cpp | 11 +- DDEve/root7/WebDisplay.cpp | 2 +- DDG4/examples/run.C | 1 + .../Geant4DetectorGeometryConstruction.cpp | 135 ++++++++++++++---- DDG4/src/Geant4Converter.cpp | 60 ++++---- .../Check_Shape_Eightpoint_Reflect_Z.xml | 42 ++++++ examples/ClientTests/scripts/Check_shape.py | 6 +- 11 files changed, 268 insertions(+), 102 deletions(-) create mode 100644 examples/ClientTests/compact/Check_Shape_Eightpoint_Reflect_Z.xml diff --git a/DDCore/include/DD4hep/Volumes.h b/DDCore/include/DD4hep/Volumes.h index 223319aa8..d91565313 100644 --- a/DDCore/include/DD4hep/Volumes.h +++ b/DDCore/include/DD4hep/Volumes.h @@ -317,6 +317,10 @@ namespace dd4hep { /// Assignment operator (must match copy constructor) Volume& operator=(const Volume& a) = default; + /// Set flag to enable copy number checks when inserting new nodes + /** By default checks are enabled. If you want to disable, call this function */ + static void enableCopyNumberCheck(bool value); + /// Check if placement is properly instrumented Object* data() const; diff --git a/DDCore/include/XML/UnicodeValues.h b/DDCore/include/XML/UnicodeValues.h index 283f9ef21..9cfbbf03e 100644 --- a/DDCore/include/XML/UnicodeValues.h +++ b/DDCore/include/XML/UnicodeValues.h @@ -390,6 +390,9 @@ UNICODE (readouts); UNICODE (ref); UNICODE (reflect); UNICODE (reflect_rot); +UNICODE (reflect_x); +UNICODE (reflect_y); +UNICODE (reflect_z); UNICODE (region); UNICODE (regions); UNICODE (regionref); diff --git a/DDCore/src/Volumes.cpp b/DDCore/src/Volumes.cpp index 03dac1cd0..6b9dc56c4 100644 --- a/DDCore/src/Volumes.cpp +++ b/DDCore/src/Volumes.cpp @@ -61,6 +61,9 @@ template <typename T> static typename T::Object* _userExtension(const T& v) { ClassImp(PlacedVolumeExtension) namespace { + + static bool s_verifyCopyNumbers = true; + TGeoVolume* _createTGeoVolume(const string& name, TGeoShape* s, TGeoMedium* m) { geo_volume_t* e = new geo_volume_t(name.c_str(),s,m); e->SetUserExtension(new Volume::Object()); @@ -263,7 +266,6 @@ namespace { } return vol; } - } /// Default constructor @@ -486,6 +488,11 @@ Volume::Volume(const string& nam, const string& title, const Solid& sol, const M m_element->SetTitle(title.c_str()); } +/// Set flag to enable copy number checks when inserting new nodes +void Volume::enableCopyNumberCheck(bool value) { + s_verifyCopyNumbers = value; +} + /// Check if placement is properly instrumented Volume::Object* Volume::data() const { Volume::Object* o = _userExtension(*this); @@ -598,31 +605,44 @@ PlacedVolume _addNode(TGeoVolume* par, TGeoVolume* daughter, int id, TGeoMatrix* as->ComputeBBox(); } } - geo_node_t* n; - TString nam_id = TString::Format("%s_%d", daughter->GetName(), id); - n = static_cast<geo_node_t*>(parent->GetNode(nam_id)); - if ( n != 0 ) { - printout(ERROR,"PlacedVolume","++ Attempt to add already exiting node %s",(const char*)nam_id); + if ( transform->IsRotation() ) { + TGeoRotation* rot = (TGeoRotation*)transform; + Double_t det = rot->Determinant(); + const Double_t* r = rot->GetRotationMatrix(); + Double_t dd = r[0] + r[4] + r[8] - 3.0; + + if ( TMath::Abs(dd) < 1E-12) transform->ResetBit(TGeoMatrix::kGeoRotation); + else transform->SetBit(TGeoMatrix::kGeoRotation); + /// We have a left handed matrix (determinant < 0). This is a reflection! + if ( det < 0e0 ) { + transform->SetBit(TGeoMatrix::kGeoReflection); + printout(INFO, "PlacedVolume", + "REFLECTION: (x.Cross(y)).Dot(z): %8.3g Parent: %s [%s] Daughter: %s [%s]", + det, par->GetName(), par->IsA()->GetName(), + daughter->GetName(), daughter->IsA()->GetName()); + } } - parent->AddNode(daughter, id, transform); + if ( s_verifyCopyNumbers ) { + TObjArray* a = parent->GetNodes(); + for (Int_t i=0, m=parent->GetNdaughters(); i < m; i++) { + TGeoNode *n = (TGeoNode*)a->UncheckedAt(i); + if ( n->GetNumber() == id ) { + printout(ERROR,"PlacedVolume", + "++ Severe error: Attempt to add already exiting copy number %d %s", + n->GetNumber(), n->GetName()); + } + } + } + geo_node_t* n {nullptr}; + /* n = */ parent->AddNode(daughter, id, transform); //n = static_cast<geo_node_t*>(parent->GetNode(id)); - n = static_cast<geo_node_t*>(parent->GetNode(nam_id)); + //n = static_cast<geo_node_t*>(parent->GetNode(nam_id)); + n = static_cast<geo_node_t*>(parent->GetNodes()->Last()); n->geo_node_t::SetUserExtension(new PlacedVolume::Object()); return PlacedVolume(n); } PlacedVolume _addNode(TGeoVolume* par, Volume daughter, int copy_nr, const Rotation3D& rot3D) { - Position x,y,z; - Rotation3D rot = rot3D; - rot.GetComponents(x,y,z); - bool left_handed = (x.Cross(y)).Dot(z) < 0; - if ( left_handed ) { - // The reflected volume already scales Z with -1 to be left-handed - // We have to accomplish for and undo this when placing the volume - rot *= Rotation3D(1., 0., 0., 0., 1., 0., 0., 0., -1.); - daughter = daughter.reflect(); - //cout << "REFLECTION: (x.Cross(y)).Dot(z) " << (x.Cross(y)).Dot(z) << endl; - } TGeoRotation r; double elements[9]; rot3D.GetComponents(elements); @@ -632,21 +652,12 @@ PlacedVolume _addNode(TGeoVolume* par, Volume daughter, int copy_nr, const Rotat } PlacedVolume _addNode(TGeoVolume* par, Volume daughter, int copy_nr, const Transform3D& tr) { - Position x, y, z, pos3D; + TGeoRotation r; + double elements[9]; + Position pos3D; Rotation3D rot3D; tr.GetRotation(rot3D); tr.GetTranslation(pos3D); - rot3D.GetComponents(x,y,z); - bool left_handed = (x.Cross(y)).Dot(z) < 0; - if ( left_handed ) { - // The reflected volume already scales Z with -1 to be left-handed - // We have to accomplish for and undo this when placing the volume - rot3D *= Rotation3D(1., 0., 0., 0., 1., 0., 0., 0., -1.); - daughter = daughter.reflect(); - //cout << "REFLECTION: (x.Cross(y)).Dot(z) " << (x.Cross(y)).Dot(z) << endl; - } - TGeoRotation r; - double elements[9]; rot3D.GetComponents(elements); r.SetMatrix(elements); auto matrix = make_unique<TGeoCombiTrans>(TGeoTranslation(pos3D.x(), pos3D.y(), pos3D.z()),r); diff --git a/DDCore/src/plugins/ShapePlugins.cpp b/DDCore/src/plugins/ShapePlugins.cpp index 0bb0878b4..aaa8a5ebc 100644 --- a/DDCore/src/plugins/ShapePlugins.cpp +++ b/DDCore/src/plugins/ShapePlugins.cpp @@ -610,14 +610,17 @@ static Ref_t create_shape(Detector& description, xml_h e, Ref_t /* sens */) { PlacedVolume pv; int count = 0; for ( xml_coll_t itm(e, _U(check)); itm; ++itm, ++count ) { - xml_dim_t x_check = itm; - xml_comp_t shape (x_check.child(_U(shape))); - xml_dim_t pos (x_check.child(_U(position), false)); - xml_dim_t rot (x_check.child(_U(rotation), false)); - bool reflect = x_check.hasChild(_U(reflect)); + xml_dim_t x_check = itm; + xml_comp_t shape (x_check.child(_U(shape))); + xml_dim_t pos (x_check.child(_U(position), false)); + xml_dim_t rot (x_check.child(_U(rotation), false)); + bool reflect = x_check.hasChild(_U(reflect)); + bool reflectZ = x_check.hasChild(_U(reflect_z)); + bool reflectY = x_check.hasChild(_U(reflect_y)); + bool reflectX = x_check.hasChild(_U(reflect_x)); + string shape_type = shape.typeStr(); Solid solid; Volume volume; - string shape_type = shape.typeStr(); if ( shape_type == "CAD_Assembly" || shape_type == "CAD_MultiVolume" ) { volume = xml::createVolume(description, shape_type, shape); @@ -633,11 +636,23 @@ static Ref_t create_shape(Detector& description, xml_h e, Ref_t /* sens */) { if ( pos.ptr() && rot.ptr() ) { Rotation3D rot3D(RotationZYX(rot.z(0),rot.y(0),rot.x(0))); Position pos3D(pos.x(0),pos.y(0),pos.z(0)); - if ( reflect ) - rot3D = Rotation3D(1., 0., 0., 0., 1., 0., 0., 0., -1.) * rot3D; Transform3D tr(rot3D, pos3D); + if ( reflect ) { + rot3D = Rotation3D(1., 0., 0., 0., 1., 0., 0., 0., -1.) * rot3D; + tr = Transform3D(rot3D, pos3D); + } + else if ( reflectX ) { + tr = Transform3D(rot3D, pos3D) * Rotation3D(-1.,0.,0.,0.,1.,0.,0.,0.,1.); + } + else if ( reflectY ) { + tr = Transform3D(rot3D, pos3D) * Rotation3D(1.,0.,0.,0.,-1.,0.,0.,0.,1.); + } + else if ( reflectZ ) { + tr = Transform3D(rot3D, pos3D) * Rotation3D(1.,0.,0.,0.,1.,0.,0.,0.,-1.); + } pv = assembly.placeVolume(volume,tr); } +#if 0 else if ( pos.ptr() ) { pv = assembly.placeVolume(volume,Position(pos.x(0),pos.y(0),pos.z(0))); } @@ -650,7 +665,7 @@ static Ref_t create_shape(Detector& description, xml_h e, Ref_t /* sens */) { else { pv = assembly.placeVolume(volume); } - +#endif if ( x_check.hasAttr(_U(id)) ) { pv.addPhysVolID("check",x_check.id()); } diff --git a/DDDetectors/src/ReflectedDetector_geo.cpp b/DDDetectors/src/ReflectedDetector_geo.cpp index 3d7bb5bd1..853c80c26 100644 --- a/DDDetectors/src/ReflectedDetector_geo.cpp +++ b/DDDetectors/src/ReflectedDetector_geo.cpp @@ -61,12 +61,13 @@ static Ref_t create_element(Detector& description, xml_h e, Ref_t sens) { matrix::_decompose(ref_pv.matrix(), tr3D, rot3D); tr3D = tr3D * (-1.0 / dd4hep::mm); } - if ( x_refl && ::toupper(x_refl.attr<string>(_U(type))[0]) == 'Z' ) - transform3D = Transform3D(Rotation3D( 1., 0., 0., 0., 1., 0., 0., 0., -1.) * rot3D, tr3D); - else if ( x_refl && ::toupper(x_refl.attr<string>(_U(type))[0]) == 'Y' ) - transform3D = Transform3D(Rotation3D( 1., 0., 0., 0., -1., 0., 0., 0., 1.) * rot3D, tr3D); - else if ( x_refl && ::toupper(x_refl.attr<string>(_U(type))[0]) == 'X' ) + char refl_type = ::toupper(x_refl.attr<string>(_U(type))[0]); + if ( x_refl && refl_type == 'X' ) transform3D = Transform3D(Rotation3D(-1., 0., 0., 0., 1., 0., 0., 0., 1.) * rot3D, tr3D); + else if ( x_refl && refl_type == 'Y' ) + transform3D = Transform3D(Rotation3D( 1., 0., 0., 0., -1., 0., 0., 0., 1.) * rot3D, tr3D); + else if ( x_refl && refl_type == 'Z' ) + transform3D = Transform3D(Rotation3D( 1., 0., 0., 0., 1., 0., 0., 0., -1.) * rot3D, tr3D); else // Z is default transform3D = Transform3D(Rotation3D( 1., 0., 0., 0., 1., 0., 0., 0., -1.) * rot3D, tr3D); pv = mother.placeVolume(vol, transform3D); diff --git a/DDEve/root7/WebDisplay.cpp b/DDEve/root7/WebDisplay.cpp index 51d95ea4d..065036bb8 100644 --- a/DDEve/root7/WebDisplay.cpp +++ b/DDEve/root7/WebDisplay.cpp @@ -54,7 +54,7 @@ static long webdisplay(Detector& description, int argc, char** argv) { cout << "Usage: -plugin <name> -arg [-arg] \n" " -detector <string> Top level DetElement path. Default: '/world' \n" - " -option <string> ROOT Draw option. Default: 'ogl' \n" + " -option <string> ROOT Draw option. Default: '' \n" " -level <number> Visualization level [TGeoManager::SetVisLevel] Default: 4 \n" " -visopt <number> Visualization option [TGeoManager::SetVisOption] Default: 1 \n" "\tArguments given: " << arguments(argc,argv) << endl << flush; diff --git a/DDG4/examples/run.C b/DDG4/examples/run.C index edba4399c..b709250da 100644 --- a/DDG4/examples/run.C +++ b/DDG4/examples/run.C @@ -17,6 +17,7 @@ // C/C++ include files #include <string> + // Run a ROOT macro void run(const char* macro) { int status; diff --git a/DDG4/plugins/Geant4DetectorGeometryConstruction.cpp b/DDG4/plugins/Geant4DetectorGeometryConstruction.cpp index d79460163..01c13b887 100644 --- a/DDG4/plugins/Geant4DetectorGeometryConstruction.cpp +++ b/DDG4/plugins/Geant4DetectorGeometryConstruction.cpp @@ -61,6 +61,10 @@ namespace dd4hep { /// Write GDML file int writeGDML(const char* gdml_output); + /// Print geant4 volume + int printVolumeObj(const char* vol_path, PlacedVolume pv); + /// Print geant4 volume tree + int printVolumeTree(const char* vol_path); /// Print geant4 volume int printVolume(const char* vol_path); /// Check geant4 volume @@ -95,6 +99,8 @@ namespace dd4hep { #include <DDG4/Geant4Kernel.h> #include <DDG4/Factories.h> +#include <TGeoScaledShape.h> + // Geant4 include files #include <G4LogicalVolume.hh> #include <G4PVPlacement.hh> @@ -199,39 +205,110 @@ int Geant4DetectorGeometryConstruction::printMaterial(const char* mat_name) { return 0; } +/// Print geant4 volume +int Geant4DetectorGeometryConstruction::printVolumeObj(const char* vol_path, PlacedVolume pv) { + if ( pv.isValid() ) { + const G4LogicalVolume* vol = 0; + auto& g4map = Geant4Mapping::instance().data(); + auto pit = g4map.g4Placements.find(pv.ptr()); + auto vit = g4map.g4Volumes.find(pv.volume()); + if ( vit != g4map.g4Volumes.end() ) { + vol = (*vit).second; + auto* sol = vol->GetSolid(); + const auto* mat = vol->GetMaterial(); + const auto* ion = mat->GetIonisation(); + Solid sh = pv.volume().solid(); + printP2("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); + printP2("+++ Dump of GEANT4 solid: %s", vol_path); + cout << mat; + if ( ion ) { + cout << " MEE: "; + cout << setprecision(12); + cout << ion->GetMeanExcitationEnergy()/CLHEP::eV; + cout << " [eV]"; + } + else + cout << " MEE: UNKNOWN"; + cout << endl << *sol; + printP2("+++ Dump of ROOT solid: %s", vol_path); + sh->InspectShape(); + if ( sh->IsA() == TGeoScaledShape::Class() ) { + TGeoScaledShape* scaled = (TGeoScaledShape*)sh.ptr(); + const Double_t* scale = scaled->GetScale()->GetScale(); + double dot = scale[0]*scale[1]*scale[2]; + printP2("+++ TGeoScaledShape: %8.3g %8.3g %8.3g [%s]", scale[0], scale[1], scale[2], + dot > 0e0 ? "RIGHT handed" : "LEFT handed"); + } + else if ( pit != g4map.g4Placements.end() ) { + const G4VPhysicalVolume* pl = (*pit).second; + const G4RotationMatrix* rot = pl->GetRotation(); + const G4ThreeVector& tr = pl->GetTranslation(); + G4Transform3D transform(rot ? *rot : G4RotationMatrix(), tr); + HepGeom::Scale3D sc; + HepGeom::Rotate3D rr; + G4Translate3D tt; + transform.getDecomposition(sc,rr,tt); + double dot = sc(0,0)*sc(1,1)*sc(2,2); + printP2("+++ TGeoShape: %8.3g %8.3g %8.3g [%s]", sc(0,0), sc(1,1), sc(2,2), + dot > 0e0 ? "RIGHT handed" : "LEFT handed"); + } + const TGeoMatrix* m = pv->GetMatrix(); + printP2("+++ TGeoMatrix: %s", + m->TestBit(TGeoMatrix::kGeoReflection) ? "LEFT handed" : "RIGHT handed"); + printP2("+++ Shape: %s cubic volume: %8.3g mm^3 area: %8.3g mm^2", + sol->GetName().c_str(), sol->GetCubicVolume(), sol->GetSurfaceArea()); + return 1; + } + else { + auto ai = g4map.g4AssemblyVolumes.find(pv.ptr()); + if ( ai != g4map.g4AssemblyVolumes.end() ) { + Volume v = pv.volume(); + warning("+++ printVolume: volume %s is an assembly...need to resolve imprint",vol_path); + for(Int_t i=0; i < v->GetNdaughters(); ++i) { + TGeoNode* dau_nod = v->GetNode(i); + string p = vol_path + string("/") + dau_nod->GetName(); + printVolumeObj(p.c_str(), dau_nod); + } + return 0; + } + } + warning("+++ printVolume: FAILED to find the volume %s in geant4 mapping...",vol_path); + return 0; + } + warning("+++ printVolume: FAILED to dump invalid volume",vol_path); + return 0; +} + /// Print geant4 volume int Geant4DetectorGeometryConstruction::printVolume(const char* vol_path) { if ( vol_path ) { - Detector& det = context()->kernel().detectorDescription(); + Detector& det = context()->kernel().detectorDescription(); PlacedVolume top = det.world().placement(); - PlacedVolume pv = detail::tools::findNode(top, vol_path); - if ( pv.isValid() ) { - auto& g4map = Geant4Mapping::instance().data(); - auto it = g4map.g4Volumes.find(pv.volume()); - if ( it != g4map.g4Volumes.end() ) { - const G4LogicalVolume* vol = (*it).second; - auto* sol = vol->GetSolid(); - const auto* mat = vol->GetMaterial(); - const auto* ion = mat->GetIonisation(); - printP2("+++ Dump of GEANT4 solid: %s", vol_path); - cout << mat; - if ( ion ) { - cout << " MEE: "; - cout << setprecision(12); - cout << ion->GetMeanExcitationEnergy()/CLHEP::eV; - cout << " [eV]"; + PlacedVolume pv = detail::tools::findNode(top, vol_path); + return printVolumeObj(vol_path, pv); + } + warning("+++ printVolume: Property VolumePath not set. [Ignored]"); + return 0; +} + +/// Print geant4 volume +int Geant4DetectorGeometryConstruction::printVolumeTree(const char* vol_path) { + if ( vol_path ) { + string p = vol_path; + Detector& det = context()->kernel().detectorDescription(); + PlacedVolume top = det.world().placement(); + PlacedVolume pv = detail::tools::findNode(top, vol_path); + if ( printVolumeObj(p.c_str(), pv) ) { + TGeoVolume* vol = pv->GetVolume(); + for(Int_t i=0; i < vol->GetNdaughters(); ++i) { + PlacedVolume dau_pv(vol->GetNode(i)); + //TGeoMatrix* tr = d->GetMatrix(); + string path = (p + "/") + dau_pv.name(); + warning("+++ printVolume: %s -> %s", dau_pv.name(), p.c_str()); + if ( printVolumeTree(path.c_str()) ) { } - else - cout << " MEE: UNKNOWN"; - cout << endl << *sol; - printP2("+++ Dump of ROOT solid: %s", vol_path); - pv.volume().solid()->InspectShape(); - printP2("+++ Shape: %s cubic volume: %8.3g mm^3 area: %8.3g mm^2", - sol->GetName().c_str(), sol->GetCubicVolume(), sol->GetSurfaceArea()); - return 1; } } - warning("+++ printVolume: FAILED to find the volume %s from the top volume",vol_path); } warning("+++ printVolume: Property VolumePath not set. [Ignored]"); return 0; @@ -240,9 +317,9 @@ int Geant4DetectorGeometryConstruction::printVolume(const char* vol_path) { /// Check geant4 volume int Geant4DetectorGeometryConstruction::checkVolume(const char* vol_path) { if ( vol_path ) { - Detector& det = context()->kernel().detectorDescription(); + Detector& det = context()->kernel().detectorDescription(); PlacedVolume top = det.world().placement(); - PlacedVolume pv = detail::tools::findNode(top, vol_path); + PlacedVolume pv = detail::tools::findNode(top, vol_path); if ( pv.isValid() ) { auto& g4map = Geant4Mapping::instance().data(); auto it = g4map.g4Volumes.find(pv.volume()); @@ -306,6 +383,8 @@ void Geant4DetectorGeometryConstruction::installCommandMessenger() { Callback(this).make(&Geant4DetectorGeometryConstruction::writeGDML),1); m_control->addCall("printVolume", "Print Geant4 volume properties [uses argument]", Callback(this).make(&Geant4DetectorGeometryConstruction::printVolume),1); + m_control->addCall("printVolumeTree", "Print Geant4 volume tree with properties [uses argument]", + Callback(this).make(&Geant4DetectorGeometryConstruction::printVolumeTree),1); m_control->addCall("checkVolume", "Check Geant4 volume properties [uses argument]", Callback(this).make(&Geant4DetectorGeometryConstruction::checkVolume),1); m_control->addCall("printMaterial", "Print Geant4 material properties [uses argument]", diff --git a/DDG4/src/Geant4Converter.cpp b/DDG4/src/Geant4Converter.cpp index 8cb30b3d2..4ae6eac23 100644 --- a/DDG4/src/Geant4Converter.cpp +++ b/DDG4/src/Geant4Converter.cpp @@ -214,19 +214,9 @@ namespace { MyTransform3D(const double* t, const double* r = s_identity_rot) : G4Transform3D(r[0],r[1],r[2],t[0]*CM_2_MM,r[3],r[4],r[5],t[1]*CM_2_MM,r[6],r[7],r[8],t[2]*CM_2_MM) { } + MyTransform3D(Transform3D&& copy) : Transform3D(copy) {} }; -#if 0 // warning: unused function 'handleName' [-Wunused-function] - void handleName(const TGeoNode* n) { - TGeoVolume* v = n->GetVolume(); - TGeoMedium* m = v->GetMedium(); - TGeoShape* s = v->GetShape(); - string nam; - printout(DEBUG, "G4", "TGeoNode:'%s' Vol:'%s' Shape:'%s' Medium:'%s'", n->GetName(), v->GetName(), s->GetName(), - m->GetName()); - } -#endif - class G4UserRegionInformation : public G4VUserRegionInformation { public: Region region; @@ -525,7 +515,7 @@ void* Geant4Converter::handleMaterial(const string& name, Material medium) const void* Geant4Converter::handleSolid(const string& name, const TGeoShape* shape) const { G4VSolid* solid = 0; if ( shape ) { - if (0 != (solid = data().g4Solids[shape])) { + if ( 0 != (solid = data().g4Solids[shape]) ) { return solid; } TClass* isa = shape->IsA(); @@ -775,10 +765,20 @@ void* Geant4Converter::handleAssembly(const string& name, const TGeoNode* node) if ( !g4 ) { g4 = new Geant4AssemblyVolume(); for(Int_t i=0; i < mot_vol->GetNdaughters(); ++i) { - TGeoNode* d = mot_vol->GetNode(i); - TGeoVolume* dau_vol = d->GetVolume(); - TGeoMatrix* tr = d->GetMatrix(); + TGeoNode* d = mot_vol->GetNode(i); + TGeoVolume* dau_vol = d->GetVolume(); + TGeoMatrix* tr = d->GetMatrix(); + TGeoRotation* rot = tr->IsRotation() ? (TGeoRotation*)tr : 0; MyTransform3D transform(tr->GetTranslation(),tr->IsRotation() ? tr->GetRotationMatrix() : s_identity_rot); + + if ( rot && rot->Determinant() < 0e0 ) { + transform = transform * G4ReflectZ3D(); + printout(ALWAYS, "Geant4Converter", "+++ Assembly: **** : Placing reflected volume. dau:%s " + "to mother %s Tr:x=%8.3f y=%8.3f z=%8.3f", + dau_vol->GetName(), mot_vol->GetName(), + transform.dx(), transform.dy(), transform.dz()); + } + if ( dau_vol->IsA() == TGeoVolumeAssembly::Class() ) { Geant4GeometryMaps::AssemblyMap::iterator assIt = info.g4AssemblyVolumes.find(d); if ( assIt == info.g4AssemblyVolumes.end() ) { @@ -836,12 +836,20 @@ void* Geant4Converter::handlePlacement(const string& name, const TGeoNode* node) node->IsA()->GetName(), vol); } else { - int copy = node->GetNumber(); - bool node_is_assembly = vol->IsA() == TGeoVolumeAssembly::Class(); - bool mother_is_assembly = mot_vol ? mot_vol->IsA() == TGeoVolumeAssembly::Class() : false; + G4Transform3D Ta; + int copy = node->GetNumber(); + TGeoRotation* rot = tr->IsRotation() ? (TGeoRotation*)tr : 0; + bool node_is_assembly = vol->IsA() == TGeoVolumeAssembly::Class(); + bool mother_is_assembly = mot_vol ? mot_vol->IsA() == TGeoVolumeAssembly::Class() : false; MyTransform3D transform(tr->GetTranslation(),tr->IsRotation() ? tr->GetRotationMatrix() : s_identity_rot); Geant4GeometryMaps::VolumeMap::const_iterator volIt = info.g4Volumes.find(mot_vol); + if ( rot && rot->Determinant() < 0e0 ) { + printout(ALWAYS, "Geant4Converter", "+++ Placement: **** : Placing reflected volume. dau:%s " + "to mother %s Tr:x=%8.3f y=%8.3f z=%8.3f", + vol->GetName(), mot_vol->GetName(), + transform.dx(), transform.dy(), transform.dz()); + } if ( mother_is_assembly ) { // // Mother is an assembly: @@ -875,13 +883,15 @@ void* Geant4Converter::handlePlacement(const string& name, const TGeoNode* node) } G4LogicalVolume* g4vol = info.g4Volumes[vol]; G4LogicalVolume* g4mot = info.g4Volumes[mot_vol]; - g4 = new G4PVPlacement(transform, // no rotation - g4vol, // its logical volume - name, // its name - g4mot, // its mother (logical) volume - false, // no boolean operations - copy, // its copy number - checkOverlaps); + G4PhysicalVolumesPair pvPlaced = + G4ReflectionFactory::Instance()->Place(transform, // no rotation + name, // its name + g4vol, // its logical volume + g4mot, // its mother (logical) volume + false, // no boolean operations + copy, // its copy number + checkOverlaps); + g4 = pvPlaced.second ? pvPlaced.second : pvPlaced.first; } info.g4Placements[node] = g4; } diff --git a/examples/ClientTests/compact/Check_Shape_Eightpoint_Reflect_Z.xml b/examples/ClientTests/compact/Check_Shape_Eightpoint_Reflect_Z.xml new file mode 100644 index 000000000..fbb097688 --- /dev/null +++ b/examples/ClientTests/compact/Check_Shape_Eightpoint_Reflect_Z.xml @@ -0,0 +1,42 @@ +<lccdd> + <includes> + <gdmlFile ref="CheckShape.xml"/> + </includes> + + <detectors> + <detector id="1" name="Shape_Eightpoint" type="DD4hep_TestShape_Creator"> + + <check vis="Shape1_vis"> + <shape type="EightPointSolid" dz="30*cm"> + <vertex x="-30*cm" y="-25*cm"/> + <vertex x="-25*cm" y=" 25*cm"/> + <vertex x=" 5*cm" y=" 25*cm"/> + <vertex x=" 25*cm" y="-25*cm"/> + <vertex x="-28*cm" y="-23*cm"/> + <vertex x="-23*cm" y=" 27*cm"/> + <vertex x="-23*cm" y=" 27*cm"/> + <vertex x=" 13*cm" y="-27*cm"/> + </shape> + <position x="0" y="0" z="100"/> + <rotation x="0" y="0" z="0"/> + </check> + + <check vis="Shape2_vis"> + <shape type="EightPointSolid" dz="30*cm"> + <vertex x="-30*cm" y="-25*cm"/> + <vertex x="-25*cm" y=" 25*cm"/> + <vertex x=" 5*cm" y=" 25*cm"/> + <vertex x=" 25*cm" y="-25*cm"/> + <vertex x="-28*cm" y="-23*cm"/> + <vertex x="-23*cm" y=" 27*cm"/> + <vertex x="-23*cm" y=" 27*cm"/> + <vertex x=" 13*cm" y="-27*cm"/> + </shape> + <position x="0" y="0" z="-100"/> + <rotation x="0" y="0" z="0"/> + <reflect_z/> + </check> + <testnot type="DD4hep_Mesh_Verifier" ref="${DD4hepExamplesINSTALL}/examples/ClientTests/ref/Ref_Eightpoint_Reflect_Z.txt" create="1" a="CheckShape_create"/> + </detector> + </detectors> +</lccdd> diff --git a/examples/ClientTests/scripts/Check_shape.py b/examples/ClientTests/scripts/Check_shape.py index 0d60c9841..69f8f9354 100644 --- a/examples/ClientTests/scripts/Check_shape.py +++ b/examples/ClientTests/scripts/Check_shape.py @@ -56,9 +56,9 @@ def run(): # # '/ddg4/ConstructGeometry/writeGDML test.gdml', ui.Commands = [ - '/ddg4/ConstructGeometry/printVolume /world_volume_1/Shape_Test_0/Shape_Test_vol_0_0', - '/ddg4/UI/exit' - ] + '/ddg4/ConstructGeometry/printVolume /world_volume_1/Shape_Test_0/Shape_Test_vol_0_0', + '/ddg4/UI/exit' + ] kernel.NumEvents = 0 kernel.configure() kernel.initialize() -- GitLab