00001 #include "AutoPositionerTool.h"
00002
00003 #include "GaudiKernel/SmartDataPtr.h"
00004 #include "GaudiKernel/MsgStream.h"
00005
00006 #include "DetDesc/LVolume.h"
00007 #include "DetDesc/PVolume.h"
00008 #include "DetDesc/SolidBase.h"
00009 #include "DetDesc/DetectorElement.h"
00010 #include "DetDesc/IGeometryInfo.h"
00011 #include "GaudiKernel/Point3DTypes.h"
00012 #include "GaudiKernel/Transform3DTypes.h"
00013
00014 #include <string>
00015
00016 AutoPositionerTool::AutoPositionerTool(const std::string& type,
00017 const std::string& name,
00018 const IInterface* parent)
00019 : GaudiTool(type, name, parent)
00020 , m_detSvc(0)
00021 , m_coordSvc(0)
00022 {
00023 declareProperty("PhysicalVolume",m_physVolName="",
00024 "Name of the physical volume to add to geometry");
00025 declareProperty("LogicalVolume",m_logVolName="",
00026 "Name of the logical volume to associate with the physical");
00027 declareProperty("CoordinateDetElem",m_coordDetElemPath="",
00028 "Name of the detector element used for coordinates");
00029 declareProperty("Position",m_position=std::vector<double>(3,0.),
00030 "Position of the new volume in the parent coordinates");
00031 double identity[] = {1., 0., 0.,
00032 0., 1., 0.,
00033 0., 0., 1.};
00034 declareProperty("Rotation",m_rotation=std::vector<double>(identity,
00035 identity+9),
00036 "Rotation of the new volume in the parent coordinates");
00037 declareProperty("Element",m_detElemName="",
00038 "Name of the detector element to place in the TDS");
00039 declareProperty("ElementPath",m_detElemPath="/dd/Structure/DayaBay",
00040 "Path for the new detector element in the TDS");
00041 declareProperty("SubDetectorElements",
00042 m_subDetElements=std::vector< std::vector<std::string> >(),
00043 "Information for defining additional daughter detector elements");
00044 }
00045
00046 AutoPositionerTool::~AutoPositionerTool()
00047 {
00048 }
00049
00050 StatusCode AutoPositionerTool::initialize()
00051 {
00052 this->GaudiTool::initialize();
00053
00054 debug() << "AutoPositionerTool::initialize()" << endreq;
00055 StatusCode sc = service("DetectorDataSvc",m_detSvc,true);
00056 if (sc.isFailure()) return sc;
00057
00058 sc = service("CoordSysSvc",m_coordSvc,true);
00059 if (sc.isFailure()) return sc;
00060
00061 return sc;
00062 }
00063
00064 StatusCode AutoPositionerTool::reinitialize()
00065 {
00066 return StatusCode::SUCCESS;
00067 }
00068
00069 StatusCode AutoPositionerTool::finalize()
00070 {
00071 m_detSvc->release();
00072 m_coordSvc->release();
00073 return this->GaudiTool::finalize();
00074 }
00075
00076 StatusCode AutoPositionerTool::queryInterface(const InterfaceID& riid,
00077 void** ppvInterface)
00078 {
00079 StatusCode sc = StatusCode::FAILURE;
00080 if (ppvInterface) {
00081 *ppvInterface = 0;
00082
00083 if (IPositionerTool::interfaceID().versionMatch(riid)) {
00084 *ppvInterface = static_cast<IPositionerTool*>(this);
00085 sc = StatusCode::SUCCESS;
00086 addRef();
00087 }
00088 else sc = GaudiTool::queryInterface( riid, ppvInterface );
00089 }
00090 return sc;
00091 }
00092
00093
00095
00097 StatusCode AutoPositionerTool::placeVolume()
00098 {
00099
00100
00101 IDetectorElement* coordDetElem = getDet<IDetectorElement>(m_coordDetElemPath);
00102 if(!coordDetElem){
00103 error() << "AutoPositionerTool::placeVolume(): "
00104 << "could not find detector element at: " << m_coordDetElemPath
00105 << endreq;
00106 return StatusCode::FAILURE;
00107 }
00108
00109
00110 Gaudi::XYZPoint referencePosition(m_position[0],m_position[1],m_position[2]);
00111 Gaudi::XYZPoint globalPosition =
00112 coordDetElem->geometry()->toGlobal( referencePosition );
00113
00114 info() << "Using " << coordDetElem->name()
00115 << " as reference system for placement of " << m_detElemName
00116 << " at local position " << referencePosition
00117 << " and global position " << globalPosition << endreq;
00118
00119
00120 IDetectorElement* parentDetElem = m_coordSvc->belongsToDE(globalPosition);
00121 if(!parentDetElem){
00122 error() << "AutoPositionerTool::placeVolume(): "
00123 << "could not find detector element at global position: "
00124 << globalPosition << endreq;
00125 return StatusCode::FAILURE;
00126 }
00127 info() << "Using " << parentDetElem->name()
00128 << " as supporting element for placement of "
00129 << m_detElemName << endreq;
00130
00131
00132
00133
00134
00135 IGeometryInfo* startGeom = parentDetElem->geometry();
00136 ILVolume::PVolumePath pvPath;
00137 StatusCode sc =
00138 parentDetElem->geometry()->fullGeoInfoForPoint(globalPosition, -1,
00139 startGeom, pvPath);
00140 if(!sc.isSuccess()){
00141 error() << "AutoPositionerTool::placeVolume(): "
00142 << "could not find parent geometry at global position: "
00143 << globalPosition << endreq;
00144 return StatusCode::FAILURE;
00145 }
00146 info() << "FullGeoInfoForPoint: " << startGeom->lvolumeName() << endreq;
00147 ILVolume::PVolumePath::iterator pvPathIter, pvPathEnd = pvPath.end();
00148 std::string npath;
00149 std::string parentLVolName = startGeom->lvolumeName();
00150 for(pvPathIter = pvPath.begin(); pvPathIter != pvPathEnd; pvPathIter++){
00151 parentLVolName = (*pvPathIter)->lvolumeName();
00152 if( npath.size() > 0 ) npath.append( "/" );
00153 npath.append( (*pvPathIter)->name() );
00154 info() << " npath: " << npath << endreq;
00155 }
00156 if( npath.size() > 0 ){
00157 error() << "Parent volume " << parentLVolName
00158 << " must have a defined detector element."
00159 << " Please define a detector element, and then you can place "
00160 << m_logVolName << " inside." << endreq;
00161 return StatusCode::FAILURE;
00162 }
00163 info() << "Using " << parentLVolName
00164 << " as parent volume for placement of " << m_logVolName << endreq;
00165 IGeometryInfo* parentGeometry = parentDetElem->geometry();
00166
00167
00168 SmartDataPtr<LVolume> parentLogVol(m_detSvc, parentLVolName);
00169 if(!parentLogVol){
00170 error() << "AutoPositionerTool::placeVolume(): "
00171 << "could not find parent volume of name: " << parentLVolName
00172 << endreq;
00173 return StatusCode::FAILURE;
00174 }
00175
00176
00177 bool pvolumeExists = false;
00178 ILVolume::PVolumes::const_iterator pvIter = parentLogVol->pvBegin();
00179 for(;pvIter != parentLogVol->pvEnd(); pvIter++){
00180 if((*pvIter)->name() == m_physVolName){
00181 warning() << "AutoPositionerTool::placeVolume(): "
00182 << "physical volume " << m_physVolName
00183 << " already exists in parent volume " << parentLVolName
00184 << endreq;
00185 pvolumeExists = true;
00186 break;
00187 }
00188 }
00189
00190 if( !pvolumeExists ){
00191
00192
00193 Gaudi::XYZPoint localPosition = parentGeometry->toLocal( globalPosition );
00194 Gaudi::XYZPoint parGlobalPosition =
00195 parentGeometry->toGlobal( Gaudi::XYZPoint(0.,0.,0.) );
00196 info() << "Parent Global position is " << parGlobalPosition << endreq;
00197 info() << "CoordRef Global position is " << globalPosition << endreq;
00198 info() << "Difference is " << parGlobalPosition - globalPosition << endreq;
00199 info() << "Placing " << m_detElemName
00200 << " at " << localPosition << " in parent volume "
00201 << parentLVolName<< endreq;
00202
00203
00204 if( parentLogVol->isInside(localPosition) ){
00205 info() << "Yep, position " << localPosition
00206 << "is inside " << parentLVolName<< endreq;
00207 }else{
00208 info() << "Ack! Position " << localPosition
00209 << "is not inside " << parentLVolName << endreq;
00210 }
00211
00212 {
00213 const SolidBase* solid = dynamic_cast<const SolidBase*>(parentLogVol->solid());
00214 info() << "X-extent: " << solid->xMin() << " " << solid->xMax() << endreq;
00215 info() << "Y-extent: " << solid->yMin() << " " << solid->yMax() << endreq;
00216 info() << "Z-extent: " << solid->zMin() << " " << solid->zMax() << endreq;
00217 }
00218 {
00219 SmartDataPtr<LVolume> logVol(m_detSvc, m_logVolName);
00220 const SolidBase* solid = dynamic_cast<const SolidBase*>(logVol->solid());
00221 info() << "X-extent: " << solid->xMin() << " " << solid->xMax() << endreq;
00222 info() << "Y-extent: " << solid->yMin() << " " << solid->yMax() << endreq;
00223 info() << "Z-extent: " << solid->zMin() << " " << solid->zMax() << endreq;
00224 }
00225
00226
00227 Gaudi::Rotation3D rotation(m_rotation.begin(), m_rotation.end());
00228 IPVolume* pv =
00229 parentLogVol->createPVolume(m_physVolName, m_logVolName,
00230 Gaudi::Transform3D(rotation, Gaudi::XYZVector(localPosition)).Inverse() );
00231
00232 if( 0 == pv ) {
00233 error() << "AutoPositionerTool::placeVolume(): "
00234 << "could not create volume: " << m_physVolName
00235 << endreq;
00236 return StatusCode::FAILURE;
00237 }
00238 }
00239
00240 if(m_detElemName != ""){
00241
00242 std::string pvPath = npath;
00243 if(pvPath.size() > 0) npath.append( "/" );
00244 pvPath.append( m_physVolName );
00245
00246 sc = addDetectorElement(m_detElemName, m_detElemPath, m_logVolName,
00247 parentDetElem->name(), pvPath);
00248 if( !sc.isSuccess() ) return sc;
00249
00250
00251 std::vector< std::vector<std::string> >::iterator sdIter,
00252 sdEnd = m_subDetElements.end();
00253 for(sdIter = m_subDetElements.begin(); sdIter != sdEnd; sdIter++){
00254 std::vector<std::string> fields = *sdIter;
00255 if( fields.size() != 4 ){
00256 error() << "Wrong number of sub-detector element fields: "
00257 << fields.size() << endreq;
00258 for(int fieldIdx=0; fieldIdx<fields.size(); fieldIdx++){
00259 error() << " Field " << fieldIdx << ": " << fields[fieldIdx]
00260 <<endreq;
00261 }
00262 return StatusCode::FAILURE;
00263 }
00264 std::string subDetElemName = fields[0];
00265 std::string support = fields[1];
00266 std::string logVolName = fields[2];
00267 std::string subPvPath = fields[3];
00268 sc = addDetectorElement(subDetElemName, m_detElemPath, logVolName,
00269 support, subPvPath);
00270 if( !sc.isSuccess() ) return sc;
00271 }
00272 }
00273
00274 return sc;
00275 }
00276
00277 StatusCode AutoPositionerTool::addDetectorElement(std::string detElemName,
00278 std::string detElemPath,
00279 std::string logVolName,
00280 std::string support,
00281 std::string npath){
00282
00283 info() << "Using " << support
00284 << " as support path for placement of " << detElemName
00285 << " at path " << detElemPath << endreq;
00286 DetectorElement* detElem = new DetectorElement;
00287 StatusCode sc = m_detSvc->registerObject( detElemPath, detElemName, detElem);
00288 if( sc.isFailure() ){
00289 error() << "Failed to register object with support / name: "
00290 << support << " / " << detElemName << endreq;
00291 return sc;
00292 }
00293 info() << "Using physical path " << npath
00294 << "relative to support " << support
00295 << " for placement of " << logVolName << endreq;
00296 detElem->createGeometryInfo( logVolName, support, npath);
00297 return sc;
00298 }