00001
00010 #include "GtPositionerTool.h"
00011
00012 #include "GaudiKernel/IssueSeverity.h"
00013 #include "GaudiKernel/IRndmGenSvc.h"
00014 #include "GaudiKernel/DataObject.h"
00015 #include "GaudiKernel/Point3DTypes.h"
00016
00017
00018 #include "DetDesc/SolidBox.h"
00019 #include "DetDesc/ILVolume.h"
00020 #include "DetDesc/IPVolume.h"
00021 #include "DetDesc/IDetectorElement.h"
00022 #include "DetDesc/IGeometryInfo.h"
00023
00024 #include "HepMC/GenEvent.h"
00025 #include "HepMC/GenVertex.h"
00026
00027 #include "CLHEP/Vector/LorentzVector.h"
00028
00029 GtPositionerTool::GtPositionerTool(const std::string& type,
00030 const std::string& name,
00031 const IInterface* parent)
00032 : GaudiTool(type,name,parent)
00033 , m_position(3,0)
00034 , m_spread(0)
00035 , m_really_initialized(false)
00036 , m_min(3,0)
00037 , m_max(3,0)
00038 , m_detelem(0)
00039 {
00040 declareInterface<IHepMCEventMutator>(this);
00041
00042 declareProperty("Volume",m_volume="",
00043 "Name (TDS path) of physical volume in which to position events");
00044 declareProperty("Strategy",m_strategy="FullVolume",
00045 "Strategy for positioning events.");
00046 declareProperty("Mode",m_mode="Uniform","Mode for choosing positions.");
00047 declareProperty("Position",m_position,"Fixed/mean point");
00048 declareProperty("Spread",m_spread,"Spread for Gausian/Uniform smearing");
00049 declareProperty("FillVolumes",m_fillVolumes,
00050 "Logical volume names to fill with generated events");
00051 declareProperty("FillMaterials",m_fillMaterials,
00052 "Material names to fill with generated events");
00053 }
00054
00055 GtPositionerTool::~GtPositionerTool()
00056 {
00057 }
00058
00059 const IDetectorElement* GtPositionerTool::detelem()
00060 {
00061 if (m_detelem) return m_detelem;
00062
00063 if ("" == m_volume) return 0;
00064
00065 if (!existDet<IDetectorElement>(m_volume)) return 0;
00066
00067 m_detelem = getDet<IDetectorElement>(m_volume);
00068 return m_detelem;
00069 }
00070
00071 StatusCode GtPositionerTool::initialize()
00072 {
00073 return StatusCode::SUCCESS;
00074 }
00075
00076 StatusCode GtPositionerTool::really_initialize()
00077 {
00078 m_really_initialized = true;
00079
00080 const IDetectorElement* detelem = this->detelem();
00081 if (!detelem) {
00082 fatal() << "Could not get detector element: \"" << m_volume << "\"" << endreq;
00083 return StatusCode::FAILURE;
00084 }
00085
00086
00087 const ILVolume* lvol = detelem->geometry()->lvolume();
00088 if (!lvol) {
00089 fatal() << "Could not get volume: \"" << m_volume << "\"" << endreq;
00090 return StatusCode::FAILURE;
00091 }
00092
00093 const SolidBase* solid = dynamic_cast<const SolidBase*>(lvol->solid());
00094 m_min[0] = solid->xMin(); m_max[0] = solid->xMax();
00095 m_min[1] = solid->yMin(); m_max[1] = solid->yMax();
00096 m_min[2] = solid->zMin(); m_max[2] = solid->zMax();
00097
00098
00099 for (int ind=0; ind<3; ++ind) {
00100 if (m_min[ind] > m_position[ind] || m_max[ind] < m_position[ind]) {
00101
00102 warning() << "GtPositioner tool given position not in detector element "
00103 << m_volume << "'s logical volume's " << *lvol
00104 << " bounding box, index " << ind << ": "
00105 << m_min[ind] << " ? " << m_position[ind] << " ? " << m_max[ind]
00106 << endreq;
00107
00108 }
00109 }
00110
00111
00112
00113
00114 if (m_mode == "Uniform") {
00115 for (int ind=0; ind<3; ++ind) {
00116 if (m_min[ind] < m_position[ind] - m_spread)
00117 m_min[ind] = m_position[ind] - m_spread;
00118 if (m_max[ind] > m_position[ind] + m_spread)
00119 m_max[ind] = m_position[ind] + m_spread;
00120 }
00121 }
00122
00123
00124 IRndmGenSvc *rgs = 0;
00125 if (service("RndmGenSvc",rgs,true).isFailure()) {
00126 fatal() << "Failed to get random service" << endreq;
00127 return StatusCode::FAILURE;
00128 }
00129 if (m_uni.initialize(rgs, Rndm::Flat(0,1)).isFailure()) {
00130 fatal() << "Failed to initialize uniform random numbers" << endreq;
00131 return StatusCode::FAILURE;
00132 }
00133 if (m_gauss.initialize(rgs, Rndm::Gauss(0,1)).isFailure()) {
00134 fatal() << "Failed to initialize Gaussian random numbers" << endreq;
00135 return StatusCode::FAILURE;
00136 }
00137
00138 return StatusCode::SUCCESS;
00139 }
00140
00141 StatusCode GtPositionerTool::finalize()
00142 {
00143 return StatusCode::SUCCESS;
00144 }
00145
00146 StatusCode GtPositionerTool::mutate(HepMC::GenEvent& event)
00147 {
00148 if (! m_really_initialized) {
00149 info() << "really_initialized with detector element: \""
00150 << m_volume << "\"" << endreq;
00151 StatusCode sc = this->really_initialize();
00152 if (sc.isFailure()) return sc;
00153 }
00154
00155
00156
00157 if ("Fixed" == m_mode or "Relative" == m_mode) {
00158 this->setPosition(m_position,event);
00159 return StatusCode::SUCCESS;
00160 }
00161
00162
00163 std::vector<double> local_pos(3,0);
00164 if (this->genPosition(local_pos)) {
00165 this->setPosition(local_pos,event);
00166 return StatusCode::SUCCESS;
00167 }
00168
00169 fatal() << "Failed to generate position" << endreq;
00170 return StatusCode::FAILURE;
00171 }
00172
00173 bool GtPositionerTool::getPoint(std::vector<double>& pos)
00174 {
00175
00176
00177 if ("Smeared" == m_mode) {
00178 for (int ind=0; ind<3; ++ind) {
00179 do {
00180 pos[ind] = m_gauss() * m_spread + m_position[ind];
00181 } while(pos[ind] < m_min[ind] || pos[ind] > m_max[ind]);
00182 }
00183 return true;
00184 }
00185
00186
00187 if ("Uniform" == m_mode) {
00188 for (int ind=0; ind<3; ++ind)
00189 pos[ind] = m_uni() * (m_max[ind]-m_min[ind]) + m_min[ind];
00190 return true;
00191 }
00192
00193
00194 fatal() << "Unknown positioning mode: " << m_mode << endreq;
00195 return false;
00196 }
00197
00198
00199 bool GtPositionerTool::genPosition(std::vector<double>& local_pos)
00200 {
00201 if ("Surface" == m_strategy) {
00202
00203
00204
00205
00206 fatal() << "Surface strategy not yet supported" << endreq;
00207 return false;
00208 }
00209
00210
00211 if (!this->getPoint(local_pos)) {
00212 fatal () << "Failed to get local point" << endreq;
00213 return false;
00214 }
00215
00216 Gaudi::XYZPoint local_point(local_pos[0],local_pos[1],local_pos[2]);
00217
00218
00219 const ILVolume* lvol = m_detelem->geometry()->lvolume();
00220 if (!lvol) {
00221 fatal() << "Could not get volume: \"" << m_volume << "\"" << endreq;
00222 return false;
00223 }
00224
00225
00226 if (!lvol->isInside(local_point))
00227 return this->genPosition(local_pos);
00228
00229 if ("AvoidDaughters" == m_strategy) {
00230
00231 ILVolume::ReplicaPath replicaPath;
00232 if (lvol->belongsTo(local_point,1,replicaPath).isFailure()){
00233 fatal() << "Invalid point in " << m_volume << ": " << local_point
00234 << endreq;
00235 }
00236
00237 if (replicaPath.size() == 0)
00238 return true;
00239 else
00240 return this->genPosition(local_pos);
00241 } else if("VolumeType" == m_strategy || "Material" == m_strategy) {
00242
00243
00244 ILVolume::PVolumePath pVolumePath;
00245
00246 if (lvol->belongsTo(local_point,-1,pVolumePath).isFailure()){
00247 fatal() << "Invalid point in " << m_volume << ": " << local_point
00248 << endreq;
00249 }
00250
00251
00252
00253
00254
00255 if (pVolumePath.size() == 0){
00256
00257 if("Material" == m_strategy){
00258 if(std::find(m_fillMaterials.begin(), m_fillMaterials.end(),
00259 lvol->materialName()) != m_fillMaterials.end()){
00260 debug() << "Placing in " << lvol->name() << endreq;
00261 return true;
00262 }
00263 }
00264 if("VolumeType" == m_strategy){
00265 if(std::find(m_fillVolumes.begin(), m_fillVolumes.end(),
00266 baseName(lvol->name())) == m_fillVolumes.end()){
00267
00268 return this->genPosition(local_pos);
00269 }
00270 }
00271 return this->genPosition(local_pos);
00272 }else{
00273 const IPVolume* lastPV = pVolumePath[pVolumePath.size() - 1];
00274
00275
00276
00277
00278 if("VolumeType" == m_strategy){
00279 if(std::find(m_fillVolumes.begin(), m_fillVolumes.end(),
00280 baseName(lastPV->lvolumeName())) == m_fillVolumes.end()){
00281
00282 return this->genPosition(local_pos);
00283 }
00284 }
00285 if("Material" == m_strategy){
00286 std::string currentMaterial =
00287 baseName(lastPV->lvolume()->materialName());
00288
00289 if(std::find(m_fillMaterials.begin(), m_fillMaterials.end(),
00290 currentMaterial) == m_fillMaterials.end()){
00291
00292 return this->genPosition(local_pos);
00293 }
00294 }
00295 debug() << "Placing in " << lastPV->name() << endreq;
00296 return true;
00297 }
00298 } else if ("FullVolume" == m_strategy) {
00299 return true;
00300 }
00301
00302 fatal() << "Failed to generate volume using strategy " << m_strategy << endreq;
00303 return false;
00304 }
00305
00306 std::string GtPositionerTool::baseName(const std::string& path){
00307 size_t pos = path.rfind('/');
00308 if( pos == std::string::npos ) return path;
00309 return path.substr(pos+1);
00310 }
00311
00312 #include "CLHEP/Units/SystemOfUnits.h"
00313
00314 void GtPositionerTool::setPosition(std::vector<double>& vpos, HepMC::GenEvent& event)
00315 {
00316 HepMC::FourVector position(vpos[0],vpos[1],vpos[2],0);
00317 debug() << "Setting position: "
00318 <<position.x()<<","<<position.y()<<","<<position.z()
00319 << endreq;
00320 HepMC::GenEvent::vertex_iterator vtx, done = event.vertices_end();
00321 for (vtx = event.vertices_begin(); vtx != done; ++vtx) {
00322 if ("Relative" == m_mode) {
00323 HepMC::FourVector relative_pos = (*vtx)->position();
00324 (*vtx)->set_position(HepMC::FourVector(position.x()+relative_pos.x(),
00325 position.y()+relative_pos.y(),
00326 position.z()+relative_pos.z(),
00327 position.t()+relative_pos.t()));
00328 }
00329 else{
00330 HepMC::FourVector position4d = position;
00331 position4d.setT((*vtx)->position().t());
00332 (*vtx)->set_position(position4d);
00333 debug() << "\tvertex @ " << "("
00334 << (*vtx)->position().x()/CLHEP::cm << ","
00335 << (*vtx)->position().y()/CLHEP::cm << ","
00336 << (*vtx)->position().z()/CLHEP::cm << ","
00337 << (*vtx)->position().t()/CLHEP::second << ") [cm,cm,cm,second]" << endreq;
00338
00339 }
00340 }
00341 }