diff --git a/DDCore/include/DD4hep/Alignment.h b/DDCore/include/DD4hep/Alignment.h new file mode 100644 index 0000000000000000000000000000000000000000..ccf71f992d3b18ae40e2517d5b46f838af1a679b --- /dev/null +++ b/DDCore/include/DD4hep/Alignment.h @@ -0,0 +1,76 @@ +// $Id: Readout.h 951 2013-12-16 23:37:56Z Christian.Grefe@cern.ch $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_GEOMETRY_ALIGNMENT_H +#define DD4HEP_GEOMETRY_ALIGNMENT_H + +// Framework include files +#include "DD4hep/Objects.h" +#include "DD4hep/Volumes.h" +#include "TGeoPhysicalNode.h" + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /* + * Geometry namespace declaration + */ + namespace Geometry { + + class DetElement; + + /** @class Alignment Alignment.h DD4hep/Alignment.h + * + * See the documentation about the TGeoPhysicalNode for further + * details. + * + * + * @author M.Frank + * @version 1.0 + */ + class Alignment: public Handle<TGeoPhysicalNode> { + public: + /// Default constructor + Alignment(); + /// Copy constructor + Alignment(const Alignment& c); + /// Constructor to be used when reading the already parsed object + template <typename Q> Alignment(const Handle<Q>& e) + : Handle<TGeoPhysicalNode>(e) { + } + /// Initializing constructor + Alignment(const std::string& path); + /// Assignment operator + Alignment& operator=(const Alignment& c); + /// Number of nodes in this branch + int numNodes() const; + /// Access the placement of this node + PlacedVolume placement() const; + /// Access the placement of the mother of this node + PlacedVolume motherPlacement(int level_up = 1) const; + /// Access the placement of a node in the chain of placements for this branch + /** Remeber the special cases: + * nodePlacement(-1) == nodePlacement(numNodes()) = placement() + * nodePlacement(numNodes()-1) == motherPlacement() = TGeoPhysicalNode::GetMother() + * == direct mother of placement() + */ + PlacedVolume nodePlacement(int level=-1) const; + + /// Align the PhysicalNode (translation only) + int align(const Position& pos, bool check = false, double overlap = 0.001); + /// Align the PhysicalNode (rotation only) + int align(const RotationZYX& rot, bool check = false, double overlap = 0.001); + /// Align the PhysicalNode (translation + rotation) + int align(const Position& pos, const RotationZYX& rot, bool check = false, double overlap = 0.001); + }; + + } /* End namespace Geometry */ +} /* End namespace DD4hep */ +#endif /* DD4HEP_GEOMETRY_ALIGNMENT_H */ diff --git a/DDCore/include/DD4hep/Detector.h b/DDCore/include/DD4hep/Detector.h index 9bc66dde380552dd9e5e08972f8e4863ebcd94af..c5e0d91568f489bed88916cf10a4dcaf4e34def5 100644 --- a/DDCore/include/DD4hep/Detector.h +++ b/DDCore/include/DD4hep/Detector.h @@ -15,6 +15,7 @@ #include "DD4hep/Objects.h" #include "DD4hep/Volumes.h" #include "DD4hep/Readout.h" +#include "DD4hep/Alignment.h" #include "DD4hep/Segmentations.h" // C/C++ include files diff --git a/DDCore/include/DD4hep/DetectorAlignment.h b/DDCore/include/DD4hep/DetectorAlignment.h new file mode 100644 index 0000000000000000000000000000000000000000..2c2b3d6737e229bc5bafd73e7e7db9b4a66d7893 --- /dev/null +++ b/DDCore/include/DD4hep/DetectorAlignment.h @@ -0,0 +1,49 @@ +// $Id: Readout.h 951 2013-12-16 23:37:56Z Christian.Grefe@cern.ch $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_GEOMETRY_DETECTORALIGNMENT_H +#define DD4HEP_GEOMETRY_DETECTORALIGNMENT_H + +// Framework include files +#include "DD4hep/Detector.h" + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /* + * Geometry namespace declaration + */ + namespace Geometry { + + class DetElement; + + /** @class Alignment Readoutn.h DD4hep/Alignment.h + * + * @author M.Frank + * @version 1.0 + */ + class DetectorAlignment : public DetElement { + protected: + public: + /// Initializing constructor + DetectorAlignment(DetElement e); + /// Collect all placements from the detector element up to the world volume + void collectNodes(std::vector<PlacedVolume>& nodes); + /// Align the PhysicalNode of the placement of the detector element (translation only) + int align(const Position& pos, bool check = false, double overlap = 0.001); + /// Align the PhysicalNode of the placement of the detector element (rotation only) + int align(const RotationZYX& rot, bool check = false, double overlap = 0.001); + /// Align the PhysicalNode of the placement of the detector element (translation + rotation) + int align(const Position& pos, const RotationZYX& rot, bool check = false, double overlap = 0.001); + }; + + } /* End namespace Geometry */ +} /* End namespace DD4hep */ +#endif /* DD4HEP_GEOMETRY_DETECTORALIGNMENT_H */ diff --git a/DDCore/include/DD4hep/DetectorTools.h b/DDCore/include/DD4hep/DetectorTools.h new file mode 100644 index 0000000000000000000000000000000000000000..d84cb7cf6a16782fc5271e962a2b67734b6ab50d --- /dev/null +++ b/DDCore/include/DD4hep/DetectorTools.h @@ -0,0 +1,61 @@ +// $Id: Readout.h 951 2013-12-16 23:37:56Z Christian.Grefe@cern.ch $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_GEOMETRY_DETECTORTOOLS_H +#define DD4HEP_GEOMETRY_DETECTORTOOLS_H + +// Framework include files +#include "DD4hep/Detector.h" + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /* + * Geometry namespace declaration + */ + namespace Geometry { + + /** @class Detectortools DetectorTools.h DD4hep/Detectortools.h + * + * @author M.Frank + * @version 1.0 + */ + class DetectorTools { + public: + typedef std::vector<DetElement> ElementPath; + typedef std::vector<PlacedVolume> PlacementPath; + /// Collect detector elements to the top detector element (world) + static void elementPath(DetElement elt, ElementPath& detectors); + /// Collect detector elements to any parent detector element + static void elementPath(DetElement parent, DetElement elt, ElementPath& detectors); + /// Collect detector elements placements to the top detector element (world) [fast, but may have holes!] + static void elementPath(DetElement elt, PlacementPath& nodes); + + /// Collect detector elements placements to the top detector element (world) [no holes!] + static void placementPath(DetElement elt, PlacementPath& nodes); + /// Collect detector elements placements to the parent detector element [no holes!] + static void placementPath(DetElement parent, DetElement child, PlacementPath& nodes); + /// Find Child of PlacedVolume and assemble on the fly the path of PlacedVolumes + static bool findChild(PlacedVolume parent, PlacedVolume child, PlacementPath& path); + /// Create cached matrix to transform to positions to an upper level Placement + static TGeoMatrix* placementTrafo(const PlacementPath& nodes, bool inverse); + + /// Find path between the child element and the parent element + static bool findParent(DetElement parent, DetElement child, ElementPath& detectors); + /// Assemble the path of the PlacedVolume selection + static std::string elementPath(const ElementPath& nodes); + /// Assemble the path of the PlacedVolume selection + static std::string nodePath(const PlacementPath& nodes); + + }; + + } /* End namespace Geometry */ +} /* End namespace DD4hep */ +#endif /* DD4HEP_GEOMETRY_DETECTORTOOLS_H */ diff --git a/DDCore/include/DD4hep/Printout.h b/DDCore/include/DD4hep/Printout.h index bcfcf0ca2255aaa863b20d124eaf6cc87963ee9c..2f8f4251d4cb10f72ba32290a430b113d60fd439 100644 --- a/DDCore/include/DD4hep/Printout.h +++ b/DDCore/include/DD4hep/Printout.h @@ -39,7 +39,7 @@ namespace DD4hep { } enum PrintLevel { - NOLOG = 0, VERBOSE, DEBUG, INFO, WARNING, ERROR, FATAL, ALWAYS + NOLOG = 0, VERBOSE=1, DEBUG=2, INFO=3, WARNING=4, ERROR=5, FATAL=6, ALWAYS }; typedef size_t (*output_function_t)(void*, PrintLevel severity, const char*, const char*); diff --git a/DDCore/include/DD4hep/Readout.h b/DDCore/include/DD4hep/Readout.h index 9830fa13003e112dea43e3f6a5e1c0b080c1e53b..992ead8043368576b6dc756ce2403a72a3c294a0 100644 --- a/DDCore/include/DD4hep/Readout.h +++ b/DDCore/include/DD4hep/Readout.h @@ -74,35 +74,6 @@ namespace DD4hep { Segmentation segmentation() const; }; - /** @class Alignment Readoutn.h DD4hep/lcdd/Readout.h - * - * @author M.Frank - * @version 1.0 - */ - struct Alignment: public Ref_t { - struct Object: public TNamed { - Volume volume; - /// Standard constructor - Object(); - /// Default destructor - virtual ~Object(); - }; - /// Default constructor - Alignment() - : Ref_t() { - } - /// Constructor to be used when reading the already parsed object - template <typename Q> Alignment(const Handle<Q>& e) - : Ref_t(e) { - } - /// Initializing constructor - Alignment(const LCDD& doc, const std::string& name); - /// Additional data accessor - Object& _data() const { - return *data<Object>(); - } - }; - /** @class Conditions Readout.h DD4hep/lcdd/Readout.h * * @author M.Frank diff --git a/DDCore/include/DD4hep/VolumeManager.h b/DDCore/include/DD4hep/VolumeManager.h index 31419cc42e446d228c43f66512aa41730351e4fb..4efa16e5215742f79fb30e9266a68fb6c934422b 100644 --- a/DDCore/include/DD4hep/VolumeManager.h +++ b/DDCore/include/DD4hep/VolumeManager.h @@ -268,7 +268,7 @@ namespace DD4hep { const TGeoMatrix& worldTransformation(VolumeID volume_id) const; }; -/// Enable printouts for debugging + /// Enable printouts for debugging std::ostream& operator<<(std::ostream& os, const VolumeManager& m); } /* End namespace Geometry */ diff --git a/DDCore/src/Alignment.cpp b/DDCore/src/Alignment.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9002451402923eecdee8240c64c817f28915137f --- /dev/null +++ b/DDCore/src/Alignment.cpp @@ -0,0 +1,106 @@ +// $Id: Readout.cpp 985 2014-01-30 13:50:10Z markus.frank@cern.ch $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework include files +#include "DD4hep/Alignment.h" +#include "DD4hep/InstanceCount.h" +#include "MatrixHelpers.h" + +// ROOT include files +#include "TGeoMatrix.h" + +using namespace std; +using namespace DD4hep; +using namespace DD4hep::Geometry; + +namespace { + int _align(TGeoPhysicalNode* n, TGeoMatrix* transform, bool check, double overlap) { + if ( n ) { + n->Align(transform, 0, check, overlap); + return 1; + } + throw runtime_error("DD4hep: Cannot align non existing physical node."); + } +} + +/// Default constructor +Alignment::Alignment() : Handle<TGeoPhysicalNode>() { +} + +/// Copy constructor +Alignment::Alignment(const Alignment& c) : Handle<TGeoPhysicalNode>(c) { +} + +/// Initializing constructor to create a new object +Alignment::Alignment(const string& path) { + //assign(new TGeoPhysicalNode(path.c_str()), path, "*"); + m_element = new TGeoPhysicalNode(path.c_str()); +} + +/// Assignment operator +Alignment& Alignment::operator=(const Alignment& c) { + if ( &c != this ) { + m_element = c.ptr(); + } + return *this; +} + +/// Number of nodes in this branch +int Alignment::numNodes() const { + if ( isValid() ) { + return ptr()->GetLevel(); + } + throw runtime_error("DD4hep: Attempt to access invalid aignment object. [Invalid Handle]"); +} + +/// Access the placement of this node +PlacedVolume Alignment::placement() const { + if ( isValid() ) { + return PlacedVolume(ptr()->GetNode(0)); + } + throw runtime_error("DD4hep: Attempt to access invalid aignment object. [Invalid Handle]"); +} + +/// Access the placement of a node in the chain of placements for this branch +PlacedVolume Alignment::nodePlacement(int level) const { + if ( isValid() ) { + PlacedVolume pv = PlacedVolume(ptr()->GetNode(level)); + if ( pv.isValid() ) return pv; + throw runtime_error("DD4hep: The object chain of "+string(placement().name())+ + " is too short. [Invalid index]"); + } + throw runtime_error("DD4hep: Attempt to access invalid aignment object. [Invalid Handle]"); +} + +/// Access the placement of the mother of this node +PlacedVolume Alignment::motherPlacement(int level_up) const { + if ( isValid() ) { + Int_t ind = ptr()->GetLevel()-level_up; + if ( ind >= 0 ) { + return PlacedVolume(ptr()->GetMother(level_up)); + } + throw runtime_error("DD4hep: This object "+string(placement().name())+" has not enough mothers. [Invalid index]"); + } + throw runtime_error("DD4hep: Attempt to access invalid aignment object. [Invalid Handle]"); +} + +/// Align the PhysicalNode (translation only) +int Alignment::align(const Position& pos, bool check, double overlap) { + return _align(ptr(),_translation(pos), check, overlap); +} + +/// Align the PhysicalNode (rotation only) +int Alignment::align(const RotationZYX& rot, bool check, double overlap) { + return _align(ptr(),_rotationZYX(rot), check, overlap); +} + +/// Align the PhysicalNode (translation + rotation) +int Alignment::align(const Position& pos, const RotationZYX& rot, bool check, double overlap) { + return _align(ptr(),_transform(pos,rot), check, overlap); +} diff --git a/DDCore/src/Detector.cpp b/DDCore/src/Detector.cpp index fbcadad981f2b4ab48b5afb458783072d4c5aaed..9f103ddd79056f7548ac6fed424abc6fecd8c9ca 100644 --- a/DDCore/src/Detector.cpp +++ b/DDCore/src/Detector.cpp @@ -9,6 +9,7 @@ #include "DD4hep/InstanceCount.h" #include "DD4hep/IDDescriptor.h" +#include "DD4hep/DetectorTools.h" #include "DD4hep/LCDD.h" #include "TGeoVolume.h" #include "TGeoMatrix.h" @@ -17,6 +18,8 @@ using namespace std; using namespace DD4hep::Geometry; +typedef DetectorTools::PlacementPath PlacementPath; +typedef DetectorTools::ElementPath ElementPath; namespace { struct ExtensionEntry { @@ -36,95 +39,6 @@ namespace { } } -static bool find_child(TGeoNode* parent, TGeoNode* child, vector<TGeoNode*>& path) { - if (parent && child) { - if (parent == child) { - path.push_back(child); - return true; - } - TIter next(parent->GetVolume()->GetNodes()); - for (TGeoNode *daughter = (TGeoNode*) next(); daughter; daughter = (TGeoNode*) next()) { - if (daughter == child) { - path.push_back(daughter); - return true; - } - } - next.Reset(); - for (TGeoNode *daughter = (TGeoNode*) next(); daughter; daughter = (TGeoNode*) next()) { - bool res = find_child(daughter, child, path); - if (res) { - path.push_back(daughter); - return res; - } - } - } - return false; -} - -static bool collect_detector_nodes(const vector<TGeoNode*>& det_nodes, vector<TGeoNode*>& nodes) { - if (det_nodes.size() < 1) { - return false; - } - if (det_nodes.size() < 2) { - return true; - } - for (size_t i = 0, n = det_nodes.size(); i < n - 1; ++i) { - if (!find_child(det_nodes[i + 1], det_nodes[i], nodes)) { - return false; - } - } - return true; -} - -/// Create cached matrix to transform to positions to an upper level DetElement -static TGeoHMatrix* create_trafo(const vector<TGeoNode*>& det_nodes) { - if (det_nodes.size() < 2) { - return new TGeoHMatrix(*gGeoIdentity); - } - vector<TGeoNode*> nodes; - if (!collect_detector_nodes(det_nodes, nodes)) { - throw runtime_error( - "DD4hep: DetElement cannot connect " + string(det_nodes[0]->GetName()) + " to child " - + string(det_nodes[1]->GetName())); - } - TGeoHMatrix* mat = new TGeoHMatrix(*gGeoIdentity); - for (vector<TGeoNode*>::const_iterator i = nodes.begin(); i != nodes.end(); ++i) { - TGeoMatrix* m = (*i)->GetMatrix(); - mat->MultiplyLeft(m); - } - return mat; -} - -/// Top detector element -static DetElement _top(DetElement o, vector<TGeoNode*>& det_nodes) { - DetElement par = o, pp = o; - while (par.isValid()) { - if (par.placement().isValid()) { - det_nodes.push_back(par.placement().ptr()); - pp = par; - } - par = par.parent(); - } - return pp; -} - -/// Top detector element -static DetElement _par(DetElement o, DetElement top, vector<TGeoNode*>& det_nodes) { - DetElement par = o, pp = o; - while (par.isValid()) { - if (par.placement().isValid()) { - det_nodes.push_back(par.placement().ptr()); - pp = par; - } - if (par.ptr() == top.ptr()) - break; - par = par.parent(); - } - if (pp.ptr() == top.ptr()) - return pp; - return DetElement(); -} - /// Default constructor DetElement::Object::Object() : TNamed(), magic(magic_word()), id(0), combineHits(0), // readout(), @@ -208,10 +122,9 @@ DetElement::Object::operator Ref_t() { /// Create cached matrix to transform to world coordinates TGeoMatrix* DetElement::Object::worldTransformation() { if (!worldTrafo) { - vector<TGeoNode*> det_nodes; - _top(DetElement(asRef()), det_nodes); - TGeoHMatrix* mat = create_trafo(det_nodes); - worldTrafo = mat; + PlacementPath nodes; + DetectorTools::placementPath(DetElement(asRef()), nodes); + worldTrafo = DetectorTools::placementTrafo(nodes,true); } return worldTrafo; } @@ -219,10 +132,9 @@ TGeoMatrix* DetElement::Object::worldTransformation() { /// Create cached matrix to transform to parent coordinates TGeoMatrix* DetElement::Object::parentTransformation() { if (!parentTrafo) { - vector<TGeoNode*> det_nodes; - det_nodes.push_back(placement.ptr()); - det_nodes.push_back(DetElement(parent).placement().ptr()); - parentTrafo = create_trafo(det_nodes); + PlacementPath nodes; + DetectorTools::placementPath(DetElement(parent), DetElement(asRef()), nodes); + parentTrafo = DetectorTools::placementTrafo(nodes,true); } return parentTrafo; } @@ -230,25 +142,25 @@ TGeoMatrix* DetElement::Object::parentTransformation() { /// Create cached matrix to transform to reference coordinates TGeoMatrix* DetElement::Object::referenceTransformation() { if (!referenceTrafo) { - vector<TGeoNode*> nodes; - DetElement ref(reference); - DetElement self(asRef()); - DetElement elt = _par(self, ref, nodes); - if (elt.isValid()) { - referenceTrafo = create_trafo(nodes); + ElementPath elements; + DetElement ref(reference); + DetElement self(asRef()); + if ( ref.ptr() == self.ptr() ) { + referenceTrafo = new TGeoHMatrix(gGeoIdentity->Inverse()); } - else { - nodes.clear(); - DetElement me(this->asRef()); - DetElement elt = _par(ref, me, nodes); - if (!elt.isValid()) { - throw runtime_error( - "DD4hep: referenceTransformation: No path from " + string(self.name()) + " to reference element " - + string(ref.name()) + " present!"); - } - TGeoMatrix* m = create_trafo(nodes); - referenceTrafo = new TGeoHMatrix(m->Inverse()); - delete m; + else if ( DetectorTools::findParent(ref,self,elements) ) { + PlacementPath nodes; + DetectorTools::placementPath(ref, self, nodes); + referenceTrafo = DetectorTools::placementTrafo(nodes,true); + } + else if ( DetectorTools::findParent(self,ref,elements) ) { + PlacementPath nodes; + DetectorTools::placementPath(self, ref, nodes); + referenceTrafo = DetectorTools::placementTrafo(nodes,true); + } + else { + throw runtime_error("DD4hep: referenceTransformation: No path from " + string(self.name()) + + " to reference element " + string(ref.name()) + " present!"); } } return referenceTrafo; @@ -313,16 +225,9 @@ string DetElement::placementPath() const { if (isValid()) { Object& o = object<Object>(); if (o.placementPath.empty()) { - string res = ""; - vector<TGeoNode*> nodes, path; - _top(*this, nodes); - if (!collect_detector_nodes(nodes, path)) { - throw runtime_error("DD4hep: DetElement cannot determine placement path of " + string(name())); - } - path.push_back(gGeoManager->GetTopNode()); - for (vector<TGeoNode*>::const_reverse_iterator i = path.rbegin(); i != path.rend(); ++i) - res += (string("/") + (*i)->GetName()); - o.placementPath = res; + PlacementPath path; + DetectorTools::placementPath(*this, path); + o.placementPath = DetectorTools::nodePath(path); } return o.placementPath; } @@ -454,7 +359,7 @@ DetElement& DetElement::setPlacement(const PlacedVolume& placement) { Object& o = object<Object>(); o.placement = placement; //o.volume = placement.volume(); - placement.setDetector(*this); + //placement.setDetector(*this); return *this; } throw runtime_error("DD4hep: DetElement::setPlacement: Placement is not defined [Invalid Handle]"); diff --git a/DDCore/src/DetectorAlignment.cpp b/DDCore/src/DetectorAlignment.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b7d58d2deea139ce58336d1a32262445b1b9d36d --- /dev/null +++ b/DDCore/src/DetectorAlignment.cpp @@ -0,0 +1,135 @@ +// $Id: Readout.cpp 985 2014-01-30 13:50:10Z markus.frank@cern.ch $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#include "DD4hep/DetectorAlignment.h" +#include "DD4hep/DetectorTools.h" +#include "DD4hep/InstanceCount.h" + +using namespace std; +using namespace DD4hep; +using namespace DD4hep::Geometry; + +typedef DetectorTools::ElementPath ElementPath; +typedef DetectorTools::PlacementPath PlacementPath; +typedef vector<pair<int,DetElement> > LevelElements; +namespace { + + Alignment& _alignment(DetectorAlignment& det) { + DetElement::Object& e = det._data(); + if ( !e.alignment.isValid() ) { + DetectorTools::PlacementPath nodes; + DetectorTools::placementPath(det,nodes); + string path = DetectorTools::nodePath(nodes); + //cout << "Align path:" << path << endl; + e.alignment = Alignment(path); + } + return e.alignment; + } + void _dumpParentElements(DetectorAlignment& det, LevelElements& elements) { + PlacementPath nodes; + ElementPath det_nodes; + DetectorTools::placementPath(det,nodes); + DetectorTools::elementPath(det,det_nodes); + /// cout << "Placement path:"; + int level = 0; + PlacementPath::const_reverse_iterator j=nodes.rbegin(); + ElementPath::const_reverse_iterator k=det_nodes.rbegin(); + for(; j!=nodes.rend(); ++j, ++level) { + //cout << "(" << level << ") " << (void*)((*j).ptr()) + // << " " << string((*j)->GetName()) << " "; + if ( ::strcmp((*j).ptr()->GetName(),(*k).placement().ptr()->GetName()) ) { + //cout << "[DE]"; + elements.push_back(make_pair(level,*k)); + ++k; + } + else { + //elements.push_back(make_pair(level,DetElement())); + } + //cout << " "; + } + //cout << endl; + } + void _patchParentElements(DetectorAlignment& det) { + DetElement::Object& obj = det._data(); + Alignment a = obj.alignment; + TGeoPhysicalNode* n = a.ptr(); + string path; + path.reserve(1024); + int level = -1; + + size_t path_len = ::strlen(a->GetName()); + for(int i = 0; i <= n->GetLevel(); ++i) { + path += "/"; + path += n->GetNode(i)->GetName(); + if ( path.length() == path_len && path == a->GetName() ) level = i; + } + //cout << "Physical node: " << path << endl; + PlacedVolume pv(n->GetNode(level)); + det.setPlacement(pv); +#if 0 + cout << "Updated placement of DetElement[" << level << "] " << det.name() + << " Placement: " << (void*)det.placement().ptr() + << " / " << n->GetNode(level) + << endl; + cout << "Placement path:"; + PlacementPath nodes; + DetectorTools::placementPath(det,nodes); + for(PlacementPath::const_reverse_iterator j=nodes.rbegin(); j!=nodes.rend(); ++j) + cout << (void*)((*j).ptr()) << " " << (*j)->GetName() << " "; + cout << endl; +#endif + cout << " Path:"; + for(int i = 0; i <= n->GetLevel(); ++i) + cout << (void*)(n->GetNode(i)) << " " << n->GetNode(i)->GetName() << " "; + cout << " / " << (void*)pv.ptr() << endl; + + TGeoNode* p = n->GetNode(n->GetLevel()-1); + TGeoNode* d = n->GetNode(n->GetLevel()); + if ( strcmp(d->GetName(),"MuonBarrel_layer9_slice1_0")==0 || + strcmp(d->GetName(),"MuonBarrel_layer9_slice9_8")==0) + { + TIter next(p->GetVolume()->GetNodes()); + // Now check next layer children + for (TGeoNode *daughter = (TGeoNode*) next(); daughter; daughter = (TGeoNode*) next()) { + cout << p->GetName() << " / " << (void*)p << " ---> " << daughter->GetName() << " " << (void*)daughter << endl; + } + } + } +} + +/// Initializing constructor +DetectorAlignment::DetectorAlignment(DetElement e) + : DetElement(e) +{ +} + +/// Collect all placements from the detector element up to the world volume +void DetectorAlignment::collectNodes(vector<PlacedVolume>& nodes) { + DetectorTools::placementPath(*this,nodes); +} + +/// Align the PhysicalNode of the placement of the detector element (translation only) +int DetectorAlignment::align(const Position& pos, bool check, double overlap) { + int result = _alignment(*this).align(pos,check,overlap); + _patchParentElements(*this); + return result; +} + +/// Align the PhysicalNode of the placement of the detector element (rotation only) +int DetectorAlignment::align(const RotationZYX& rot, bool check, double overlap) { + int result = _alignment(*this).align(rot,check,overlap); + _patchParentElements(*this); + return result; +} + +/// Align the PhysicalNode of the placement of the detector element (translation + rotation) +int DetectorAlignment::align(const Position& pos, const RotationZYX& rot, bool check, double overlap) { + int result = _alignment(*this).align(pos,rot,check,overlap); + _patchParentElements(*this); + return result; +} diff --git a/DDCore/src/DetectorTools.cpp b/DDCore/src/DetectorTools.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d919d46b18759ec686dc36b773f840726f0c3829 --- /dev/null +++ b/DDCore/src/DetectorTools.cpp @@ -0,0 +1,187 @@ +// $Id: Readout.cpp 985 2014-01-30 13:50:10Z markus.frank@cern.ch $ +//==================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +// Framework include files +#include "DD4hep/DetectorTools.h" +#include "DD4hep/Printout.h" +#include <stdexcept> +#include <memory> + +// ROOT include files +#include "TGeoMatrix.h" + +using namespace std; +using namespace DD4hep; +using namespace DD4hep::Geometry; + +/// Assemble the path of the PlacedVolume selection +std::string DetectorTools::nodePath(const PlacementPath& nodes) { + string s=""; + for(PlacementPath::const_reverse_iterator i=nodes.rbegin();i!=nodes.rend();++i) + s += "/" + string((*i)->GetName()); + return s; +} + +/// Assemble the path of the PlacedVolume selection +std::string DetectorTools::elementPath(const ElementPath& nodes) { + string s = ""; + for(ElementPath::const_reverse_iterator i=nodes.rbegin();i!=nodes.rend();++i) + s += "/" + string((*i)->GetName()); + return s; +} + +/// Collect detector elements to any parent detector element +bool DetectorTools::findParent(DetElement parent, DetElement elt, vector<DetElement>& detectors) { + detectors.clear(); + if ( parent.isValid() && elt.isValid() ) { + if ( parent.ptr() == elt.ptr() ) { + detectors.push_back(elt); + return true; + } + ElementPath elements; + for(DetElement par = elt; par.isValid(); par = par.parent()) { + elements.push_back(par); + if ( par.ptr() == parent.ptr() ) { + detectors = elements; + return true; + } + } + } + throw runtime_error("Search for parent detector element with invalid handles not allowed."); +} + +/// Find Child of PlacedVolume and assemble on the fly the path of PlacedVolumes +bool DetectorTools::findChild(PlacedVolume parent, PlacedVolume child, PlacementPath& path) { + if ( parent.isValid() && child.isValid() ) { + // Check self + if ( parent.ptr() == child.ptr() ) { + path.push_back(child); + return true; + } + TIter next(parent->GetVolume()->GetNodes()); + // Now check next layer children + for (TGeoNode *daughter = (TGeoNode*) next(); daughter; daughter = (TGeoNode*) next()) { + if ( daughter == child.ptr() ) { + path.push_back(daughter); + return true; + } + } + next.Reset(); + // Finally crawl down the tree + for (TGeoNode *daughter = (TGeoNode*) next(); daughter; daughter = (TGeoNode*) next()) { + PlacementPath sub_path; + bool res = findChild(daughter, child, sub_path); + if (res) { + path.insert(path.end(), sub_path.begin(), sub_path.end()); + path.push_back(daughter); + return res; + } + } + } + return false; +} + +/// Find Child of PlacedVolume and assemble on the fly the path of PlacedVolumes +static bool findChildByName(PlacedVolume parent, PlacedVolume child, DetectorTools::PlacementPath& path) { + if ( parent.isValid() && child.isValid() ) { + // Check self + if ( 0 == ::strcmp(parent.ptr()->GetName(),child.ptr()->GetName()) ) { + path.push_back(child); + return true; + } + TIter next(parent->GetVolume()->GetNodes()); + // Now check next layer children + for (TGeoNode *daughter = (TGeoNode*) next(); daughter; daughter = (TGeoNode*) next()) { + if ( 0 == ::strcmp(daughter->GetName(),child.ptr()->GetName()) ) { + path.push_back(daughter); + return true; + } + } + next.Reset(); + // Finally crawl down the tree + for (TGeoNode *daughter = (TGeoNode*) next(); daughter; daughter = (TGeoNode*) next()) { + DetectorTools::PlacementPath sub_path; + bool res = findChildByName(daughter, child, sub_path); + if (res) { + path.insert(path.end(), sub_path.begin(), sub_path.end()); + path.push_back(daughter); + return res; + } + } + } + return false; +} + +/// Collect detector elements to the top detector element (world) +void DetectorTools::elementPath(DetElement elt, vector<DetElement>& detectors) { + for(DetElement par = elt; par.isValid(); par = par.parent()) + detectors.push_back(par); +} + +/// Collect detector elements to any parent detector element +void DetectorTools::elementPath(DetElement parent, DetElement elt, vector<DetElement>& detectors) { + if ( findParent(parent,elt,detectors) ) + return; + throw runtime_error(string("The detector element ")+parent.name()+string(" is no parent of ")+elt.name()); +} + +/// Collect detector elements placements to the top detector element (world) [fast, but may have holes!] +void DetectorTools::elementPath(DetElement element, vector<PlacedVolume>& det_nodes) { + for(DetElement par = element; par.isValid(); par = par.parent()) { + PlacedVolume pv = par.placement(); + if ( pv.isValid() ) { + det_nodes.push_back(pv); + } + } +} + +/// Collect detector elements placements to the top detector element (world) [no holes!] +void DetectorTools::placementPath(DetElement element, vector<PlacedVolume>& nodes) { + PlacementPath det_nodes, all_nodes; + DetectorTools::elementPath(element,det_nodes); + for (size_t i = 0, n = det_nodes.size(); i < n-1; ++i) { + if (!findChildByName(det_nodes[i + 1], det_nodes[i], nodes)) { + throw runtime_error("DD4hep: DetElement cannot determine placement path of " + + string(element.name()) + " [internal error]"); + } + } + if ( det_nodes.size()>0 ) { + nodes.push_back(det_nodes.back()); + } +} + +/// Collect detector elements placements to the parent detector element [no holes!] +void DetectorTools::placementPath(DetElement parent, DetElement child, PlacementPath& nodes) { + ElementPath det_nodes; + PlacementPath all_nodes; + DetectorTools::elementPath(parent,child,det_nodes); + for (size_t i = 0, n = det_nodes.size(); i < n-1; ++i) { + if (!findChild(det_nodes[i + 1], det_nodes[i], nodes)) { + throw runtime_error("Invalid placement path "+elementPath(det_nodes)+" [internal error]"); + } + } + if ( det_nodes.size()>0 ) nodes.push_back(det_nodes.back()); +} + +/// Create cached matrix to transform to positions to an upper level Placement +TGeoMatrix* DetectorTools::placementTrafo(const PlacementPath& nodes, bool inverse) { + if (nodes.size() < 2) { + return new TGeoHMatrix(*gGeoIdentity); + } + auto_ptr<TGeoHMatrix> mat(new TGeoHMatrix(*gGeoIdentity)); + for (size_t i = 0, n=nodes.size(); n>0 && i < n-1; ++i) { + const PlacedVolume& p = nodes[i]; + TGeoMatrix* m = p->GetMatrix(); + mat->MultiplyLeft(m); + } + if ( inverse ) { + auto_ptr<TGeoHMatrix> inv(new TGeoHMatrix(mat->Inverse())); + mat = inv; + } + return mat.release(); +} diff --git a/DDCore/src/Handle.cpp b/DDCore/src/Handle.cpp index fa9e06c92c83d300f88eaa74c2cc130903407549..fe851d12558a35cf567e7540ceb923b43ec94dc0 100644 --- a/DDCore/src/Handle.cpp +++ b/DDCore/src/Handle.cpp @@ -396,7 +396,7 @@ INSTANTIATE(TGeoCompositeShape); // Volume Placements (needed by "Volumes.cpp") #include "TGeoPhysicalNode.h" -INSTANTIATE_UNNAMED(TGeoPhysicalNode); +INSTANTIATE(TGeoPhysicalNode); // Replicated Volumes (needed by "Volumes.cpp") #include "TGeoPatternFinder.h" diff --git a/DDCore/src/LCDDImp.cpp b/DDCore/src/LCDDImp.cpp index ecc31e5ca98eee888be1d68d494d3227c1b6385d..9b3bc261b35a22f9b9a7ae7d867a02eecc46e02e 100644 --- a/DDCore/src/LCDDImp.cpp +++ b/DDCore/src/LCDDImp.cpp @@ -113,8 +113,8 @@ LCDDImp::LCDDImp() } { m_manager = gGeoManager; - m_manager->AddNavigator(); - m_manager->SetCurrentNavigator(0); + //m_manager->AddNavigator(); + //m_manager->SetCurrentNavigator(0); //cout << "Navigator:" << (void*)m_manager->GetCurrentNavigator() << endl; } //if ( 0 == gGeoIdentity ) diff --git a/DDCore/src/MatrixHelpers.cpp b/DDCore/src/MatrixHelpers.cpp index 4e82874375b190eff43768901e2ac1ed1f45ecab..31f3e54d92d2f32481359d3898f2175dcd38dec6 100644 --- a/DDCore/src/MatrixHelpers.cpp +++ b/DDCore/src/MatrixHelpers.cpp @@ -31,12 +31,6 @@ TGeoRotation* DD4hep::Geometry::_rotation3D(const Rotation3D& rot3D) { } TGeoHMatrix* DD4hep::Geometry::_transform(const Transform3D& trans) { -#if 0 - TGeoHMatrix* tr = new TGeoHMatrix(); - Double_t* t = tr->GetTranslation(); - Double_t* r = tr->GetRotationMatrix(); - trans.GetComponents(r[0],r[1],r[2],t[0],r[3],r[4],r[5],t[1],r[6],r[7],r[8],t[2]); -#endif double t[3]; RotationZYX rot; Position pos; @@ -51,3 +45,16 @@ TGeoHMatrix* DD4hep::Geometry::_transform(const Transform3D& trans) { tr->SetDz(t[2]); return tr; } + +TGeoHMatrix* DD4hep::Geometry::_transform(const Position& pos, const RotationZYX& rot) { + double t[3]; + TGeoHMatrix *tr = new TGeoHMatrix(); + tr->RotateZ(rot.Phi() * RAD_2_DEGREE); + tr->RotateY(rot.Theta() * RAD_2_DEGREE); + tr->RotateX(rot.Psi() * RAD_2_DEGREE); + pos.GetCoordinates(t); + tr->SetDx(t[0]); + tr->SetDy(t[1]); + tr->SetDz(t[2]); + return tr; +} diff --git a/DDCore/src/MatrixHelpers.h b/DDCore/src/MatrixHelpers.h index 41c6ff58f065352d4be26afb907961e72c7c1e1c..26c54b6c1449e92164d879ebc873477453dd85db 100644 --- a/DDCore/src/MatrixHelpers.h +++ b/DDCore/src/MatrixHelpers.h @@ -33,6 +33,7 @@ namespace DD4hep { TGeoRotation* _rotationZYX(const RotationZYX& rot); TGeoRotation* _rotation3D(const Rotation3D& rot); TGeoHMatrix* _transform(const Transform3D& trans); + TGeoHMatrix* _transform(const Position& pos, const RotationZYX& rot); } /* End namespace Geometry */ } /* End namespace DD4hep */ diff --git a/DDCore/src/Readout.cpp b/DDCore/src/Readout.cpp index d6c1471ea70cbb41758d778fa7a40c3611fd6128..9aa45cff8651125ddf88fded372f96435c30a833 100644 --- a/DDCore/src/Readout.cpp +++ b/DDCore/src/Readout.cpp @@ -79,21 +79,6 @@ Segmentation Readout::segmentation() const { return object<Object>().segmentation; } -/// Standard constructor -Alignment::Object::Object() { - InstanceCount::increment(this); -} - -/// Default destructor -Alignment::Object::~Object() { - InstanceCount::decrement(this); -} - -/// Initializing constructor to create a new object -Alignment::Alignment(const LCDD& /* lcdd */, const string& nam) { - assign(new Object(), nam, "alignment"); -} - /// Standard constructor Conditions::Object::Object() { InstanceCount::increment(this); diff --git a/DDCore/src/VolumeManager.cpp b/DDCore/src/VolumeManager.cpp index 7e2fae6db35a91e67f715f44ac80195da9adcb54..8ee4adaf328d347b885e27f0caeb8abc3cf5bbc6 100644 --- a/DDCore/src/VolumeManager.cpp +++ b/DDCore/src/VolumeManager.cpp @@ -453,23 +453,44 @@ bool VolumeManager::adoptPlacement(VolumeID /* sys_id */, Context* context) { o.volumes[vid] = context; o.detMask |= context->mask; //o.phys_volumes[pv.ptr()] = context; - err << "Inserted new volume:" << setw(6) << left << o.volumes.size() << " Ptr:" << (void*) context->placement.ptr() << " [" - << context->placement.name() << "]" << " ID:" << (void*) context->identifier << " Mask:" << (void*) context->mask; + err << "Inserted new volume:" << setw(6) << left << o.volumes.size() << " Ptr:" << (void*) pv.ptr() << " [" + << pv.name() << "]" << " ID:" << (void*) context->identifier << " Mask:" << (void*) context->mask; printout(DEBUG, "VolumeManager", err.str().c_str()); return true; } - err << "Attempt to register twice volume with identical volID " << (void*) context->identifier << " Mask:" - << (void*) context->mask << " to detector " << o.detector.name() << " ptr:" << (void*) pv.ptr() << " -- " - << (*i).second->placement.ptr() << " pv:" << pv.name() << " clashes with " << (*i).second->placement.name() + err << "+++ Attempt to register duplicate volID " << (void*) context->identifier + << " Mask:" << (void*) context->mask + << " to detector " << o.detector.name() + << " ptr:" << (void*) pv.ptr() + << " Name:" << pv.name() << " Sensitive:" << (pv.volume().isSensitive() ? "YES" : "NO") << endl; + printout(ERROR, "VolumeManager", "%s", err.str().c_str()); + err.str(""); + err << " !!!!! ++++ VolIDS "; + const PlacedVolume::VolIDs::Base& ids = context->volID; + for (PlacedVolume::VolIDs::Base::const_iterator vit = ids.begin(); vit != ids.end(); ++vit) + err << (*vit).first << "=" << (*vit).second << "; "; + printout(ERROR, "VolumeManager", "%s", err.str().c_str()); + err.str(""); + context = (*i).second; + pv = context->placement; + err << " !!!!! +++ Clashing volID " << (void*) context->identifier + << " Mask:" << (void*) context->mask + << " to detector " << o.detector.name() + << " ptr:" << (void*) pv.ptr() + << " Name:" << pv.name() + << " Sensitive:" << (pv.volume().isSensitive() ? "YES" : "NO") << endl; + printout(ERROR, "VolumeManager", "%s", err.str().c_str()); + err.str(""); + goto Fail; Fail: { - err << "++++ VolIDS:"; + err << " !!!!! ++++ VolIDS "; const PlacedVolume::VolIDs::Base& ids = context->volID; for (PlacedVolume::VolIDs::Base::const_iterator vit = ids.begin(); vit != ids.end(); ++vit) err << (*vit).first << "=" << (*vit).second << "; "; } - printout(ERROR, "VolumeManager", "++++[!!!] adoptPlacement: %s", err.str().c_str()); + printout(ERROR, "VolumeManager", "%s", err.str().c_str()); // throw runtime_error(err.str()); return false; }