diff --git a/DDRec/include/DDRec/CellIDPositionConverter.h b/DDRec/include/DDRec/CellIDPositionConverter.h index 92365505e672aa6a68e69b0173a5104b2e931cbd..2f27e27382778970e3dc6a249e78d307e5d5deab 100644 --- a/DDRec/include/DDRec/CellIDPositionConverter.h +++ b/DDRec/include/DDRec/CellIDPositionConverter.h @@ -33,7 +33,7 @@ namespace DD4hep { public: /// The constructor - takes the main lcdd object. - CellIDPositionConverter( Geometry::LCDD& lcdd ) { + CellIDPositionConverter( Geometry::LCDD& lcdd ) : _lcdd( &lcdd ) { _volumeManager = Geometry::VolumeManager::getVolumeManager(lcdd); } @@ -61,6 +61,21 @@ namespace DD4hep { const Geometry::VolumeManagerContext* findContext(const CellID& cellID) const; + + /** Find the DetElement that contains the given point - if no DetElement is found, an + * invalid DetElement is returned. Uses the optionally given DetElement as start for the search. + */ + Geometry::DetElement findDetElement(const Geometry::Position& global, + const Geometry::DetElement& det=Geometry::DetElement() ) const; + + + /** Find the lowest daughter Placement in the Placement that + * contains the point (in the coordinate system of the mother placement) the local coordintates + * in this placement are also returned. + */ + Geometry::PlacedVolume findPlacement(const Geometry::Position& point, const Geometry::PlacedVolume& mother, double locPos[3]) const ; + + /** Find the readout object for the given DetElement. If the DetElement is sensitive the corresondig * Readout is returned, else a recursive search in the daughter volumes (nodes) of this DetElement's * volume is performed and the first Readout object is returned. @@ -77,6 +92,7 @@ namespace DD4hep { protected: Geometry::VolumeManager _volumeManager{} ; + const Geometry::LCDD* _lcdd ; }; diff --git a/DDRec/src/CellIDPositionConverter.cpp b/DDRec/src/CellIDPositionConverter.cpp index 21d3a324e3eee58dd7512e4e6e2d5114c0e77b34..4951548d7352bbc4a31490887e43905af4b45642 100644 --- a/DDRec/src/CellIDPositionConverter.cpp +++ b/DDRec/src/CellIDPositionConverter.cpp @@ -46,7 +46,7 @@ namespace DD4hep { DetElement det = context->element ; -#if 0 // this uses the deprected VolumeManagerContext::placement +#if 0 // this uses the deprecated VolumeManagerContext::placement PlacedVolume pv = context->placement ; @@ -85,11 +85,148 @@ namespace DD4hep { CellID CellIDPositionConverter::cellID(const Position& global) const { - //FIXME: how to best implement this ? + CellID result(0) ; + + DetElement motherDet = _lcdd->world() ; // could also start from an arbitrary DetElement here !? + + DetElement det = findDetElement( global , motherDet ) ; + + if( ! det.isValid() ) + return result ; + + double g[3], e[3] , l[3] ; + global.GetCoordinates( g ) ; + det.nominal().worldTransformation().MasterToLocal( g, e ); + + PlacedVolume pv = findPlacement( Position( e[0], e[1] , e[2] ) , det.placement() , l ) ; + + if( pv.isValid() && pv.volume().isSensitive() ) { + + Geometry::SensitiveDetector sd = pv.volume().sensitiveDetector(); + Readout r = sd.readout() ; + VolumeID volID = det.volumeID() ; + + result = r.segmentation().cellID( Position( l[0], l[1], l[2] ) , global, volID ); + + } else { + + std::cout << " *** ERROR : found non-sensitive Placement " << pv.name() + << " for point " << global << std::endl ; + } + + + return result ; + } - return 0 ; + + namespace { + + bool containsPoint( const DetElement& det, const Geometry::Position& global ) { + + if( det.volume().isValid() and det.volume().solid().isValid() ) { + + double g[3], l[3] ; + global.GetCoordinates( g ) ; + + det.nominal().worldTransformation().MasterToLocal( g, l ); + + return det.volume().solid()->Contains( l ) ; + } + + return false ; + } + } + DetElement CellIDPositionConverter::findDetElement(const Geometry::Position& global, + const DetElement& d) const { + + DetElement det = ( d.isValid() ? d : _lcdd->world() ) ; + + // std::cout << " --- " << global << det.name() << std::endl ; + + if( containsPoint( det, global ) ) { + + if( det.children().empty() ) // no children -> we are done + return det ; + + // see if we have a child DetElement that contains the point ... + + DetElement result ; + for( auto it : det.children() ){ + // std::cout << " - " << global << it.second.name() << " " << containsPoint( it.second , global ) + // << " nChild: " << it.second.children().size() << " isValid: " << it.second.isValid() + // << std::endl ; + + if( containsPoint( it.second , global ) ){ + result = it.second ; + break ; + } + } + if( result.isValid() ){ // ... yes, we have + + if( result.children().empty() ) // no more children -> done + return result ; + else + return findDetElement( global, result ) ; // keep searching in children + } + + } + + // point not contained + return DetElement() ; + } + + Geometry::PlacedVolume CellIDPositionConverter::findPlacement(const Geometry::Position& pos, const Geometry::PlacedVolume& pv , double locPos[3]) const { + + + double l[3] ; + pos.GetCoordinates( l ) ; + + std::cout << " --- " << pos << " " << pv.name() << " loc: (" << locPos[0] << "," << locPos[1] << "," << locPos[2] << ")" << std::endl ; + + if( pv.volume().solid()->Contains( l ) ) { + + int ndau = pv->GetNdaughters() ; + + if( ndau == 0 ) // no daughter volumes -> we are done + return pv ; + + // see if we have a daughter volume that contains the point ... + + PlacedVolume result ; + for (int i = 0 ; i < ndau; ++i) { + + PlacedVolume pvDau = pv->GetDaughter( i ); + pvDau->MasterToLocal( l , locPos ) ; // transform point to daughter's local frame + + std::cout << " - " << pos << " " << pvDau.name() + << " loc: (" << locPos[0] << "," << locPos[1] << "," << locPos[2] << ")" + << pvDau.volume().solid()->Contains( locPos ) + << " ndau: " << pvDau->GetNdaughters() + << std::endl ; + + + if( pvDau.volume().solid()->Contains( locPos ) ) { // point is contained in daughter node + result = pvDau ; + break ; + } + } + + if( result.isValid() ){ // ... yes, we have + + if( result->GetNdaughters() == 0 ){ // no more children -> done + return result ; + } else + return findPlacement( Position( locPos[0], locPos[1] , locPos[2] ), result , locPos ) ; // keep searching in daughter volumes + } + + } + + return PlacedVolume() ; + } + + Readout CellIDPositionConverter::findReadout(const Geometry::DetElement& det) const { @@ -120,13 +257,9 @@ namespace DD4hep { } } - // traverse the daughter nodes: - const TGeoNode* node = pv.ptr(); - - for (Int_t idau = 0, ndau = node->GetNdaughters(); idau < ndau; ++idau) { + for (Int_t idau = 0, ndau = pv->GetNdaughters(); idau < ndau; ++idau) { - TGeoNode* daughter = node->GetDaughter(idau); - PlacedVolume dpv( daughter ); + PlacedVolume dpv = pv->GetDaughter(idau); Readout r = findReadout( dpv ) ; if( r.isValid() ) return r ; diff --git a/UtilityApps/src/test_cellid_position_converter.cpp b/UtilityApps/src/test_cellid_position_converter.cpp index 2ec12ded2fb8123975f798123f5e95d48a1a278d..0f54788559f26cef5c83a5a42ec66311f6d47fbc 100644 --- a/UtilityApps/src/test_cellid_position_converter.cpp +++ b/UtilityApps/src/test_cellid_position_converter.cpp @@ -40,6 +40,8 @@ static DDTest test( "cellid_position_converter" ) ; //============================================================================= const double epsilon = dd4hep::micrometer ; +const int maxHit = 10 ; + double dist( const Position& p0, const Position& p1 ){ Position p2 = p1 - p0 ; @@ -77,7 +79,7 @@ int main_wrapper(int argc, char** argv ){ // use only hits from these collections std::set< std::string > subset = {} ; - //{"BeamCalCollection" } ; //EcalBarrelCollection" } ; //"HcalBarrelRegCollection"} ; + //{"BeamCalCollection" } ; //{"EcalBarrelCollection" } ; //{"HcalBarrelRegCollection"} ; // ignore all hits from these collections @@ -107,9 +109,11 @@ int main_wrapper(int argc, char** argv ){ std::string cellIDEcoding = col->getParameters().getStringVal("CellIDEncoding") ; - DD4hep::BitField64 idDecoder( cellIDEcoding ) ; + DD4hep::BitField64 idDecoder0( cellIDEcoding ) ; + DD4hep::BitField64 idDecoder1( cellIDEcoding ) ; - int nHit = col->getNumberOfElements() ; + int nHit = std::min( col->getNumberOfElements(), maxHit ) ; + for(int i=0 ; i< nHit ; ++i){ @@ -119,25 +123,34 @@ int main_wrapper(int argc, char** argv ){ DD4hep::long64 id1 = sHit->getCellID1() ; DD4hep::long64 id = ( id1 << 32 | id0 ) ; - idDecoder.setValue( id ) ; + idDecoder0.setValue( id ) ; Position point( sHit->getPosition()[0]* dd4hep::mm , sHit->getPosition()[1]* dd4hep::mm , sHit->getPosition()[2]* dd4hep::mm ) ; // ====== test cellID to position and positio to cellID conversion ================================ + DetElement det = idposConv.findDetElement( point ) ; - // CellID idFromDecoder = idposConv.cellID( point ) ; + CellID idFromDecoder = idposConv.cellID( point ) ; - Position pointFromDecoder = idposConv.position( id ) ; + idDecoder1.setValue( idFromDecoder ) ; + + + std::stringstream sst ; + sst << " compare ids: " << det.name() << " " << idDecoder0.valueString() << " - " << idDecoder1.valueString() ; - // test( idFromDecoder , id , " compare ids: " ) ; + test( id, idFromDecoder, sst.str() ) ; + + + Position pointFromDecoder = idposConv.position( id ) ; double d = dist(pointFromDecoder, point) ; - std::stringstream sst ; - sst << " dist " << d << " ( " << pointFromDecoder << " ) - ( " << point << " )" ; + std::stringstream sst1 ; + sst1 << " dist " << d << " ( " << point << " ) - ( " << pointFromDecoder << " ) - detElement: " + << det.name() ; - test( d < epsilon , true , sst.str() ) ; + test( d < epsilon , true , sst1.str() ) ; } }