#ifndef TGeomIdManager_hxx_seen #define TGeomIdManager_hxx_seen #include #include #include #include #include class TGeoManager; class TGeoMaterial; class TGeoNode; class TGeoHMatrix; class TGeoVolume; #include "EoaCore.hxx" #include "IGeometryId.hxx" #include "ISHA1.hxx" #include "ISHAHashValue.hxx" #include "IAlignmentId.hxx" #include "ICOMETContext.hxx" #include "HEPUnits.hxx" namespace COMET { class IHit; class IGeomIdFinder; class IGeomIdManager; class IOADatabase; class ICOMETEvent; } /// Translate IGeometryId objects into TGeoNode pointers used with /// TGeoManager. This is a singleton object managed and owned by IOADatabase. /// The geometry identifier provides a non-dynamic (and stable) way for the /// software to uniquely identify a particular volume (e.g. a scintillator /// bar, a TPC pad, &c). However, for efficiency ROOT needs to use TGeoNode /// identifiers which must be assigned dynamically when a geometry is open. /// This method builds a map between the persistent geometry identifiers and /// the dynamic node identifiers. /// /// The proper way to find out ROOT based information from a geometry /// identifier is to use IGeomIdManager::CdId(), and the interrogate the /// TGeoManager object. Some convenience routines have been provided for /// common cases (IGeomIdManager::GetPosition(), and /// IGeomIdManager::GetGeometryId()). The name of the volume associated with /// a IGeometryId object is available through IGeometryId::GetName(). class COMET::IGeomIdManager { friend class COMET::IOADatabase; friend class IGeometryId; public: enum ShapeType { kBox, kTube }; /// A type used to find a root TGeoNode in the gGeoManager, that has been /// abstracted so that it's possible to change the key type. As long as /// the geometry is small enough, this key will be a node id. typedef int RootGeoKey; /// An abstraction of the IGeometryId value that is used to find the /// RootGeoKey. The GeomIdKey is built from the IGeometryId. typedef int GeomIdKey; /// A map between a GeomIdKey key that is derived from a IGeometryId object /// and the RootGeoKey keys used to find the geometry nodes. typedef std::map GeomIdMap; /// A map between a RootGeoKey and a GeomIdKey typedef std::map RootIdMap; ~IGeomIdManager(); /// Change the current node to the IGeometryId. This changes the state of /// the gGeoManager. /// If the key is not valid, a false value will be returned. /// If the return value is true, then we can expect nothing went wrong. bool CdId(const IGeometryId& id) const; /// Get the IGeometryId value associated with the current ROOT node /// identifier. If the current node id doesn't have a geometry /// identifier, move up one level in the root geometry and checks again. /// If a geometry identifier is not found, then this returns false. bool FindGeometryId(IGeometryId& id) const; /// Get the IGeometryId value associated with a global position. The /// return value will be false if the position doesn't correspond to a /// volume identified by a IGeometryId. bool GetGeometryId(double x, double y, double z, IGeometryId& id) const; /// Get the position of the center of the geometry id. This changes the /// state of the gGeoManager to make the node associated with the geometry /// id into the current node. This position includes any affects of /// alignment applied to the gGeoManager. The return value will be false /// if the IGeometryId object is invalid. bool GetPosition(const IGeometryId& id, TVector3& position) const; bool GetPosition(const int nodeId, TVector3& position) const; /// Translate a position in the master coordinate system to a position in /// the local coordinate system of the geometry id. /// return false if the geomId is not valid bool MasterToLocal(const IGeometryId& geomId, double x, double y, double z, TVector3 & newpos) const; bool MasterToLocal(const IGeometryId& geomId, TVector3 pos, TVector3 & newpos) const {return MasterToLocal(geomId,pos.X(),pos.Y(),pos.Z(), newpos);}; /// Translate a position in the master coordinate system to a position in /// the local coordinate system of the node id. /// return fasle if the nodeId is not valid bool MasterToLocal(int nodeId, double x, double y, double z, TVector3 & newpos) const; bool MasterToLocal(int nodeId, TVector3 pos, TVector3 & newpos) const {return MasterToLocal(nodeId,pos.X(),pos.Y(),pos.Z(), newpos);}; /// Translate a vector in the master coordinate system to a vector in /// the local coordinate system of the geometry id. /// return false if the geomId is not valid bool MasterToLocalVect(const IGeometryId& geomId, double x, double y, double z, TVector3 & newvec) const; bool MasterToLocalVect(const IGeometryId& geomId, TVector3 vec, TVector3 & newvec) const{return MasterToLocalVect(geomId,vec.X(),vec.Y(),vec.Z(), newvec);}; /// Translate a vector in the master coordinate system to a vector in /// the local coordinate system of the node id. /// return false if the nodeId is not valid bool MasterToLocalVect(int nodeId, double x, double y, double z, TVector3 & newvec) const; bool MasterToLocalVect(int nodeId, TVector3 vec, TVector3 & newvec) const{return MasterToLocalVect(nodeId,vec.X(),vec.Y(),vec.Z(), newvec);}; /// Translate a position in the local coordinate system of a geometry id /// into a position in the master coordinate system. /// return false if the geomId is not valid bool LocalToMaster (const IGeometryId& geomId, double x, double y, double z, TVector3 & newpos) const; bool LocalToMaster (const IGeometryId& geomId, TVector3 pos, TVector3 & newpos) const {return LocalToMaster(geomId,pos.X(),pos.Y(),pos.Z(), newpos);}; /// Translate a position in the local coordinate system of a node id /// into a position in the master coordinate system. /// return false if the node id is not valid bool LocalToMaster (int nodeId, double x, double y, double z, TVector3 & newpos) const; bool LocalToMaster (int nodeId, TVector3 pos, TVector3 & newpos) const {return LocalToMaster(nodeId,pos.X(),pos.Y(),pos.Z(), newpos);}; /// Translate a vector in the local coordinate system of a geometry id /// into a vector in the master coordinate system. /// return false if the geomId is not valid bool LocalToMasterVect(const IGeometryId& geomId, double x, double y, double z, TVector3 & newvec) const; bool LocalToMasterVect(const IGeometryId& geomId, TVector3 vec, TVector3 & newvec) const{return LocalToMasterVect(geomId,vec.X(),vec.Y(),vec.Z(), newvec);}; /// Translate a vector in the local coordinate system of a node id /// into a vector in the master coordinate system. /// return false if the nodeId is not valid bool LocalToMasterVect(int nodeId, double x, double y, double z, TVector3 & newvec) const; bool LocalToMasterVect(int nodeId, TVector3 vec, TVector3 & newvec) const{return LocalToMasterVect(nodeId,vec.X(),vec.Y(),vec.Z(), newvec);}; /// get the pointer to TGeoNode from a given node id TGeoNode * GetNode(int nodeId) const; TGeoNode * GetNode(const IGeometryId & geomId) const; /// Find TGeoNode from given coordinate (global) TGeoNode * FindNode(double x, double y, double z) const; TGeoNode * FindNode(const TVector3 & position) const; /// Find TGeoNode from given coordinate (global) and keep gGeoManager stay at that node TGeoNode * FindNodeAndEnter(double x, double y, double z) const; TGeoNode * FindNodeAndEnter(const TVector3 & position) const; /// Find node id from given coordinate (global) int FindNodeId(double x, double y, double z) const; int FindNodeId(const TVector3 & position) const; /// get the full node path std::string FullNodePath(double x, double y, double z) const; std::string FullNodePath(const TVector3& position) const; std::string FullNodePath(int nodeId) const; /// {@ Translate a node ID into an extent in the master coordinate system. /// The node extent is defined as the "half-length" of the dimension. For /// instance, a box which is 2cmx2cmx10cm will have an extend of (1cm, /// 1cm, 5cm). This is how far the object extends from its reference /// point. TVector3 NodeExtent(const IGeometryId& geomId, ShapeType shape = kBox) const; TVector3 NodeExtent(const COMET::IHit& hit, ShapeType shape = kBox) const; // @} /// Fine the bounding box for the node in the local coordinate system. /// The bounding box is defined as the "half-length" of the dimension. /// For instance a box which is 2cmx2cmx10cm will have an extend of (1cm, /// 1cm, 5cm). This is how far the object extends from its center. TVector3 NodeSize(const IGeometryId& geomId, ShapeType shape = kBox) const; TVector3 NodeSize(const TGeoNode* node, ShapeType shape = kBox) const; /// Translate a node id into a geometry path name. std::string NodeName(COMET::IGeometryId geomId) const; /// Get the position of the center of the geometry id. TVector3 NodePosition(const IGeometryId& id) const; TVector3 NodePosition(const int nodeId) const; /// Get the affine transformation matrix of the node const TGeoHMatrix* NodeMatrix(const int nodeId) const; /// Get the geo volume of the node const TGeoVolume* NodeVolume(const int nodeId) const; /// Optioned Get radiation length ... /// Root is out by a factor 1000 for our units /// Methods: /// - 0: use (corrected) root version /// - 1: use PDG method /// - 2: use simplified PDG method double X0(TGeoMaterial * mat, int method = 0) const; /// return the default length unit used in ROOT file. Set in the constructor function. double GetRootUnitLength() const{return fRootUnitLength;}; /// Get the hash keys for the currently loaded geometry. const ISHAHashValue& GetHash() const {return fGeomIdHashCode;} /// Get the alignment id currently applied to the loaded geometry. const IAlignmentId& GetAlignmentId() const {return fGeomIdAlignmentId;} /// Provide a geometry matching a particular hash. This opens the file /// and reads the geometry. The result is provided using the TGeoManager /// global gGeoManager. If this is successful, it returns true (and /// gGeoManager will non-NULL), otherwise it returns false. If false is /// returned, then the gGeoManager pointer will not have changed. This /// requires the first hash, but the other hashs may be left to the /// default value. If the other hashs have a non-zero value, then the /// file name is searched for that hash. /// /// The geometry is found by looking in a standarized location /// (${OAEVENTROOT}/${OAEVENTCONFIG}/geometry) for a file which advertises /// a geometry matching the requested hash value. This uses LoadGeometry /// to read the geometry file. bool ReadGeometry(const ISHAHashValue& hc); /// Provide a standard method to load the geometry out of a TFile. The /// TFile must be open for input before this is called. This will return /// true if the geometry was found and it matched the hash code (or there /// was a geometry in the file named "COMETGeometry"), otherwise it will /// return false. If false is returned, then the gGeoManager pointer will /// not have changed. This uses ResetGeometry to update the state of the /// geometry manager GeometryId tables and hash codes. /// /// If an alignment id is provided, this will load the geometry matching /// both the hash code and the alignment. If it can't find a geometry /// matching both, but does find a geometry matching the hash code, that /// geometry will be loaded. bool LoadGeometry(TFile& file, const ISHAHashValue& hc = COMET::ISHAHashValue(), const IAlignmentId& align = COMET::IAlignmentId()); /// Update the state of the geometry id and hash code tables using the /// gGeoManager geometry. If gGeoManager isn't a valid geometry, then the /// tables are left in an "empty" state. This is used by LoadGeometry, /// and can be used when you have a geometry already loaded in memory /// (e.g. to update the IGeomIdManager to match the MC geometry in /// SIMG4). After this has been successfully called (returned true), /// gGeoManager will point to a geometry named /// COMETGeometry-xxxxxxxx-xxxxxxxx-xxxxxxxx-xxxxxxxx-xxxxxxxx" where "x" /// stands for a lower case hexidecimal digit. void ResetGeometry(); /// A map of geometry id represented as integers to the associated ROOT /// node id. This can be used to iterate over all of the geometry /// identifiers associated with a geometry. This exposes integers since /// it is exposing an internal table that is optimized for space. This /// table can be used /// /// \code /// for (IGeomIdManager::GeomIdMap::iterator g /// = COMET::IOADatabase::Get().GeomId().GetGeomIdMap().begin(); /// g != COMET::IOADatabase::Get().GeomId().GetGeomIdMap().end(); /// ++g) { /// IGeometryId gid(g->first); /// } /// \endcode const GeomIdMap& GetGeomIdMap() {return fGeomIdMap;} /// Provide a file to override the standard geometry. Setting the /// geometry file to any value other than "" will cause IOADatabase to /// override the standard geometry. void SetGeometryFileOverride(std::string f) {fGeometryFileOverride = f;} /// Get the name of a file to override the standard geometry. const std::string& GetGeometryFileOverride() const { return fGeometryFileOverride; } /// Set a geometry hash value to override the standard geometry. This /// resets the required hash if called without an argument. void SetGeometryHashOverride(const ISHAHashValue& h) { fGeometryHashOverride = h; } /// Set a geometry pointer to override the standard geometry. /// The geometry will be reset meanwhile, since the geometry is /// considered already prepared and no need to call LoadGeometry() later on. void SetGeometryPointerOverride(TGeoManager * geometry) { fGeometryPointerOverride = geometry; SetGeoManager(geometry); ResetGeometry(); } /// Get the hash code that has been set to override the default geometry. /// This will be "zero" if the hashcode hasn't been set. const ISHAHashValue& GetGeometryHashOverride() const { return fGeometryHashOverride; } /// Get the pointer to the geometry to override the default geometry. TGeoManager * GetGeometryPointerOverride() const { return fGeometryPointerOverride; } private: /// Construct a new IGeomIdManager. This is private since it should only /// be constructed by the friend class IOADatabase. IGeomIdManager(); /// Make the copy constructor private. IGeomIdManager(const IGeomIdManager&); /// Can't assign the class. bool operator =(const IGeomIdManager&); /// An abstraction of finding the geometry node based on the RootGeoKey. /// This is the only method that needs to change if the RootGeoKey /// definition changes. This method has the effect of changing the /// TGeoManager current node. /// If the key is not valid, a false value will be returned. /// If the return value is true, then we can expect nothing went wrong. bool CdKey(const RootGeoKey& key) const; /// Using the current gGeoManager node, build a RootGeoKey. This must /// preserve the gGeoManager state. RootGeoKey MakeRootGeoKey() const; /// Build a GeomIdKey from a IGeometryId. GeomIdKey MakeGeomIdKey(IGeometryId id) const; /// Make a IGeometryId object out of a GeomIdKey; IGeometryId MakeGeometryId(GeomIdKey key) const; /// Find the geometry path associated with a geometry identifier. This /// returns "" if the path is not available. This a private method used /// to implement IGeometryId::GetName(). std::string GetPath(IGeometryId id) const; /// Build the map between the geometry identifier and the root TGeoManager /// volumes in gGeoManager. void BuildGeomIdMap(); /// An internal method to recurse through the entire ROOT geometry. This /// does a depth first recursion through the geometry. It passes a vector /// containing the volume names for the current recursion, and will keep /// recursing down a particular branch as long as keepGoing is not zero. /// This returns the value of keepGoing which will be zero the recursion /// has been truncated. int RecurseGeomId(std::vector& names, int keepGoing); /// Save a hash code into the current gGeoManager object name. void SaveHashCode(const COMET::ISHAHashValue& hc); /// Get the hash code out of the current gGeoManager object name. This /// will return false if the gGeoManager object name does not contain the /// hash code. bool GetHashCode(COMET::ISHAHashValue& hc) const; /// Save an alignment id into the current gGeoManager object name. void SaveAlignmentCode(const COMET::IAlignmentId& hc); /// Get the alignment id out of the current gGeoManager object name. This /// will return false if the gGeoManager object name does not contain the /// id. bool GetAlignmentCode(COMET::IAlignmentId& hc) const; /// Parse the hash code out of a string. This will return false if the /// string does not contain the hash code. The string should be stripped /// of all characters up to the first hexidecimal digit, and can be either /// a the geometry hash code or the alignment id hash code. bool ParseHashCode(std::string hashCode, COMET::ISHAHashValue& hc) const; /// Calculate the geometry hash code for the current gGeoManager. Be /// aware that the result depends on the machine where it is being run. void BuildHashCode(); /// An internal method to recurse through the entire ROOT geometry. This /// does a depth first recursion through the geometry. It passes a vector /// containing the volume names for the current recursion. void RecurseHashCode(std::vector& names); /// Find a file with a geometry matching a particular hash. Looks in a /// standarized location (${OAEVENTROOT}/${OAEVENTCONFIG}/geometry) for a /// file which advertises a geometry matching the requested hash value. /// If the file is found, this returns the file name, otherwise it returns /// an empty stream. This requires the first hash, but the other hashs /// may be left to the default value. If the other hashs have a non-zero /// value, then the file name is searched for that hash. std::string FindGeometryFile(const COMET::ISHAHashValue& hc) const; /// Find and load the geometry that best matchs this event. If this /// returns true, then a new geometry was loaded. If event is non-null, /// then it will be used to try and select the best geometry. This uses /// ReadGeometry, LoadGeometry and ResetGeometry to load the actual /// geometry manager so the geometry id and hash code tables are updated /// by this method. bool FindAndLoadGeometry(COMET::ICOMETEvent* event); /// Determine if the geometry should be looked for. If this returns true, /// the a new geometry should be loaded. bool CheckGeometry(const COMET::ICOMETEvent* const event); /// Check if the alignment might have changed. bool CheckAlignment(const COMET::ICOMETEvent* const event); /// This applies the alignment. void ApplyAlignment(const COMET::ICOMETEvent* const event); /// Load the correct geometry. This is provided to IOADatabase to /// implement COMET::IOADatabase::Geometry(). TGeoManager* UpdateGeometry(COMET::ICOMETEvent* event); /// Set the pointer to the current geometry manager. This sets both the /// fGeoManager field and the gGeoManager global. void SetGeoManager(TGeoManager* g); /// Return a pointer to the currently loaded geometry TGeoManager* GetGeoManager(); /// Return a pointer to the currently loaded geometry and make sure that /// gGeoManager is pointing to the correct geometry. TGeoManager* GetGeometry(); /// Set the geometry time stamp. void SetGeomEventContext(const COMET::ICOMETContext& c) {fGeomEventContext=c;} /// Get the geometry time stamp. const COMET::ICOMETContext& GetGeomEventContext() const { return fGeomEventContext; } /// The current geometry. TGeoManager* fGeoManager; /// The map between the GeomIdKey and the RootIdKey GeomIdMap fGeomIdMap; /// The map between the RootIdKey and the GeomIdKey. RootIdMap fRootIdMap; /// The hash code for the geometry associated with fGeomIdMap and /// fRootIdMap. This is used to short circuit the BuildGeomIdMap method. ISHAHashValue fGeomIdHashCode; /// Keep track of the hash code of the last geometry the user routines /// have been told about via the ApplyGeometryCallbacks method. ISHAHashValue fGeomIdChangedHash; /// The alignment identifier associated with the current geometry. IAlignmentId fGeomIdAlignmentId; /// The context of the last event that was checked to make sure that the /// geometry was valid. This is used to short circuit the geometry check /// when the event geometry hash code and alignment id haven't been set. COMET::ICOMETContext fGeomEventContext; /// The class to calculate the ISHA1 message digest. This is used in /// RecurseHashCode. COMET::ISHA1 fSHA1; /// A vector of IGeomIdFinder objects. std::vector fFinders; /// The name of the geometry override file (if it has been set). std::string fGeometryFileOverride; /// The hash code for the geometry to be used (if it has been set). If /// this is set, then a geometry with this hash code will override the /// default geometry. ISHAHashValue fGeometryHashOverride; /// The pointer of geometry to be used. If this is set, then the geometry /// from this pointer will override the default geometry. TGeoManager * fGeometryPointerOverride; /// standard unit for length used in ROOT geometry double fRootUnitLength; double fRootUnitLength2; // square of length unit }; #endif