00001 #include "DrawHistoryAlg.h"
00002 #include "Event/SimHeader.h"
00003 #include "Event/SimParticleHistory.h"
00004 #include "Event/SimTrack.h"
00005 #include "Event/SimVertex.h"
00006 #include "Event/SimHit.h"
00007 #include "Event/SimHitHeader.h"
00008 #include "Event/SimHitCollection.h"
00009 #include "Event/SimPmtHit.h"
00010 #include "Event/SimRpcHit.h"
00011
00012 #include "DetDesc/IDetectorElement.h"
00013 #include "DetDesc/GeometryInfoPlus.h"
00014 #include "DetDesc/IPVolume.h"
00015 #include "GaudiKernel/DeclareFactoryEntries.h"
00016 #include "GaudiKernel/ParticleProperty.h"
00017 #include "GaudiKernel/IParticlePropertySvc.h"
00018
00019 #include "CLHEP/Units/SystemOfUnits.h"
00020 #include "HepMC/GenParticle.h"
00021 #include "HepMC/GenEvent.h"
00022 #include "HepMC/GenVertex.h"
00023
00024 #include <fstream>
00025 #include <sstream>
00026 #include <string>
00027
00028 DECLARE_ALGORITHM_FACTORY(DrawHistoryAlg);
00029
00030 using namespace DayaBay;
00031
00032 DrawHistoryAlg::DrawHistoryAlg(const std::string& name, ISvcLocator* pSvcLocator)
00033 : GaudiAlgorithm(name,pSvcLocator)
00034 {
00035 declareProperty("Location",m_location= DayaBay::SimHeaderLocation::Default,
00036 "Location in the TES to get Event data");
00037 declareProperty("track_filename",m_track_filename = "tracks_%d.dot",
00038 "Filename to write track structure. Use '\%d' to indicate event number.");
00039 declareProperty("trackandvertex_filename",m_trackandvertex_filename = "tracks_and_vertices_%d.dot",
00040 "Filename to write track structure. Use '\%d' to indicate event number.");
00041 declareProperty("do_hits",m_do_hits = true,
00042 "1 to make hits in track plot, 0 to ignore them.");
00043 declareProperty("Geometry",m_topGeoPath = "/dd/Structure/DayaBay",
00044 "Top level geometry structure element.");
00045 }
00046
00047 DrawHistoryAlg::~DrawHistoryAlg()
00048 {
00049 }
00050
00051 StatusCode DrawHistoryAlg::initialize()
00052 {
00053
00054 m_ppSvc =0;
00055 StatusCode sc = service("ParticlePropertySvc",m_ppSvc,true);
00056 if(sc.isFailure()){
00057 err() << "Cant' get a ParticlePropertySvc pointer." << endreq;
00058 return StatusCode::FAILURE;
00059 }
00060
00061 return StatusCode::SUCCESS;
00062 }
00063
00064 StatusCode DrawHistoryAlg::finalize()
00065 {
00066 return StatusCode::SUCCESS;
00067 }
00068
00069 std::string DrawHistoryAlg::particleName(int pdg)
00070 {
00071 ParticleProperty* p = m_ppSvc->findByStdHepID(pdg);
00072 if(p) return p->particle();
00073 std::ostringstream oss;
00074 oss << "[" << pdg << "]";
00075 return oss.str();
00076 }
00077
00078 bool DrawHistoryAlg::volumeInfo(SimVertex& v, std::string& name, std::string& material)
00079 {
00080 static IDetectorElement* topDet = getDet<IDetectorElement>(m_topGeoPath);
00081 static IDetectorElement* lastDet = 0;
00082
00083
00084 IDetectorElement* start = lastDet ? lastDet : topDet;
00085 std::string child_de_path = start->geometry()->belongsToPath(v.position(),-1);
00086
00087 if ("" == child_de_path && lastDet) {
00088 child_de_path = topDet->geometry()->belongsToPath(v.position(),-1);
00089 }
00090 IDetectorElement* child = getDet<IDetectorElement>(child_de_path);
00091
00092
00093
00094 if (!child) return false;
00095
00096
00097 lastDet = child;
00098
00099 name = child->name();
00100 material = child->geometry()->lvolume()->materialName();
00101 return true;
00102 }
00103
00104 StatusCode DrawHistoryAlg::execute()
00105 {
00106 using std::endl;
00107
00108 DayaBay::SimHeader* header = 0;
00109 if (exist<DayaBay::SimHeader>(evtSvc(),m_location)) {
00110 header = get<DayaBay::SimHeader>(m_location);
00111 }
00112 if(!header) {
00113 warning() << "No SimHeader found." <<endreq;
00114 return StatusCode::SUCCESS;
00115 }
00116
00117 const SimParticleHistory* h = header->particleHistory();
00118 if(!h) {
00119 warning() << "No SimParticleHistory found!" << endreq;
00120 return StatusCode::SUCCESS;
00121 }
00122
00123
00125
00126
00127
00128 std::string filename = m_trackandvertex_filename;
00129 {
00130 std::string::size_type dpos = filename.find("%d");
00131 if(dpos!=std::string::npos) {
00132 std::ostringstream oss;
00133 oss << header->execNumber();
00134 filename.replace(dpos,2,oss.str());
00135 }
00136 }
00137
00138 std::ofstream dot(filename.c_str());
00139 dot << "digraph G {" << endl;
00140 const std::list<SimTrack*>& tracks = h->tracks();
00141 std::list<SimTrack*>::const_iterator tit;
00142 for(tit = tracks.begin();tit!= tracks.end(); ++tit) {
00143 const SimTrack* t= *tit;
00144 const std::vector<SimVertex*>& vertices = t->vertices();
00145 dot << "// SimTrack id " << t->trackId() << endl;
00146
00147 dot << "v" << (long)(vertices[0])
00148 << " [label=\""
00149 << "SimTrack Start " << t->trackId()
00150 <<"\"]" << endl;
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162 dot << "subgraph cluster" << t->trackId() <<" {" << endl;
00163 dot << " label = \"SimTrack " << t->trackId()
00164 << "\\n" << particleName(t->particle())
00165 << "\\nparent=" << t->parentParticle()
00166 << "\\n" << "KE=" << t->vertices()[0]->kineticEnergy()/CLHEP::MeV << " MeV";
00167 for(SimTrack::descendants_map::const_iterator udit = t->unrecordedDescendants().begin();
00168 udit != t->unrecordedDescendants().end();
00169 ++udit) {
00170 dot << "\\n" << udit->second << " skipped of type " << particleName(udit->first);
00171 }
00172 dot << "\";" << endl;
00173
00174 assert(vertices.size()>0);
00175
00176
00177 for(unsigned int iv = 1; iv<vertices.size(); iv++) {
00178 dot << " v" << long(vertices[iv-1]) << " -> v" << long(vertices[iv]);
00179
00180 double dx = (vertices[iv]->position()-vertices[iv-1]->position()).R();
00181 double dE = (vertices[iv]->totalEnergy()-vertices[iv-1]->totalEnergy());
00182 dot << "[label=\""
00183 << "dx=" << dx/CLHEP::cm << " cm"
00184 << "\\ndE=" << dE/CLHEP::MeV << " MeV"
00185 << "\"]";
00186 dot << ";" << endl;
00187 }
00188
00189 dot << "}" << endl;
00190
00191 for(unsigned int iv = 0; iv<vertices.size(); iv++) {
00192 const SimVertex* v = vertices[iv];
00193 const std::vector<SimTrackReference>& secs = v->secondaries();
00194 for(unsigned int isec = 0; isec < secs.size(); ++ isec){
00195 const SimTrack* trk = secs[isec].track();
00196 if(trk) {
00197 dot << "v" << (long)v << " -> v" << (long)(trk->vertices()[0]);
00198 if(secs[isec].isIndirect())
00199 dot << "[ style = dotted ]";
00200 dot << ";" << endl;
00201 }
00202 }
00203 }
00204 }
00205
00206
00207 const std::list<SimVertex*>& verts = h->vertices();
00208 dot << endl << "// Dump of all " << verts.size() << " vertices" << endl;
00209 std::list<SimVertex*>::const_iterator vit;
00210 for(vit = verts.begin(); vit!= verts.end(); ++vit) {
00211 SimVertex* v = *vit;
00212 dot << "v" << (long)(v);
00213 dot << " [label=\"";
00214 dot << v->kineticEnergy()/CLHEP::MeV << " MeV";
00215
00216 std::string name, material;
00217 if (volumeInfo(*v,name,material)) {
00218 dot << "\\n" << name;
00219 dot << "\\n" << material;
00220 }
00221 dot << "\"]" << endl;
00222 dot << ";" << endl;
00223 }
00224 dot << "}" << endl;
00225 dot.close();
00226
00228
00229
00230
00231 filename = m_track_filename;
00232 {
00233 std::string::size_type dpos = filename.find("%d");
00234 if(dpos!=std::string::npos) {
00235 std::ostringstream oss;
00236 oss << header->execNumber();
00237 filename.replace(dpos,2,oss.str());
00238 }
00239 }
00240
00241 dot.open(filename.c_str());
00242 dot << "digraph G {" << endl;
00243
00244
00245 std::set<const HepMC::GenEvent*> primaryEvents;
00246 const std::list<const SimTrack*>& primaries = h->primaryTracks();
00247 std::list<const SimTrack*>::const_iterator it;
00248 for(it = primaries.begin();it!= primaries.end(); ++it) {
00249
00250 const HepMC::GenParticle* primaryParticle = (*it)->primaryParticle();
00251 const HepMC::GenEvent* gev = primaryParticle->parent_event();
00252 primaryEvents.insert(gev);
00253 dot << " primaryEvent" << (long)(gev) << ":genpar" << (long)(primaryParticle);
00254 dot << " -> track" << (long)(*it) << endl;
00255 }
00256
00257
00258 std::set<const HepMC::GenEvent*>::iterator gevit;
00259 for(gevit = primaryEvents.begin() ; gevit != primaryEvents.end(); gevit++){
00260 const HepMC::GenEvent* gev = *gevit;
00261 dot << " primaryEvent" << (long)(gev) << " [shape=record,rank=source,label=\"{";
00262 dot << "event " << gev->event_number() <<"\\nprocess_id=" << gev->signal_process_id() << "| {";
00263
00264 HepMC::GenEvent::particle_const_iterator parit = gev->particles_begin();
00265 while(parit != gev->particles_end()) {
00266 const HepMC::GenParticle* gpar = *parit;
00267 HepMC::FourVector momentum(gpar->momentum());
00268 double pmag = HepMC::ThreeVector(momentum).mag();
00269 double ke = momentum.e() - sqrt(momentum.e()*momentum.e() - pmag*pmag);
00270 dot << "<" << "genpar" << (long)(gpar) << "> ";
00271 dot << particleName(gpar->pdg_id())
00272 << "\\n KE=" << ke/CLHEP::MeV << " MeV";
00273 parit++;
00274 if(parit != gev->particles_end()) dot << " | ";
00275 }
00276
00277 dot << "} }\"];" << endl;
00278 }
00279
00280
00281
00282 dot << "subgraph cluster_of_the_tracks {" << endl;
00283 for(tit = tracks.begin();tit!= tracks.end(); ++tit) {
00284 const SimTrack* t= *tit;
00285 dot << "track" << (long)(t)
00286 << "[label=\""
00287 << "SimTrack " << t->trackId()
00288 << "\\n" << particleName(t->particle())
00289
00290 << "\\n" << t->vertices()[0]->process().type() << " " << t->vertices()[0]->process().name()
00291 << "\\n" << "KE=" << t->vertices()[0]->kineticEnergy()/CLHEP::MeV << " MeV"
00292 << "\\n" << "with " << t->vertices().size() << " vertices";
00293 for(SimTrack::descendants_map::const_iterator udit = t->unrecordedDescendants().begin();
00294 udit != t->unrecordedDescendants().end();
00295 ++udit) {
00296 dot << "\\n" << udit->second << " skipped of type " << particleName(udit->first);
00297 }
00298 dot << "\"];" << endl;
00299
00300 if(t->ancestorTrack().track()) {
00301 dot << "track" << (long)(t->ancestorTrack().track()) << " -> track" << (long)(t);
00302 if(! t->ancestorTrack().isDirect())
00303 dot << " [ style = dotted label=\"" << t->ancestorTrack().indirection() << "\"]";
00304 dot << ";" << endl;
00305 }
00306 }
00307 dot << "}" << endl;
00308
00309
00310
00311 if(m_do_hits) {
00312 SimHitHeader::hc_map::const_iterator hcit = header->hits()->hitCollection().begin();
00313 for( ; hcit != header->hits()->hitCollection().end(); hcit ++){
00314 const SimHitCollection* hc = hcit->second;
00315 for(unsigned int ihit = 0; ihit<hc->collection().size(); ihit++) {
00316 const SimHit* simhit = hc->collection()[ihit];
00317
00318
00319 dot << "simhit" << (long)(simhit) << "[shape=triangle,rank=sink,label=\"";
00320 if(dynamic_cast<const SimPmtHit*>(simhit)) dot << "Pmt";
00321 else if(dynamic_cast<const SimRpcHit*>(simhit)) dot << "Rpc";
00322 else dot << "Hit";
00323 dot << "\\nID="
00324 << ((simhit->sensDetId()&(0xFF000000))>>24) << "."
00325 << ((simhit->sensDetId()&(0xFF0000))>>16) << "."
00326 << ((simhit->sensDetId()&(0xFF00))>>8) << "."
00327 << ((simhit->sensDetId()&(0xFF)))
00328 <<"\"];" << endl;
00329
00330
00331 dot << " track" << (long)(simhit->ancestor().track()) << " -> simhit" << (long)(simhit);
00332 if(! simhit->ancestor().isDirect())
00333 dot << " [ headport = n, style = dotted, label=\"" << simhit->ancestor().indirection() << "\"]";
00334 dot << ";" << endl;
00335 }
00336 }
00337 }
00338
00339 dot << "}" << endl;
00340 dot.close();
00341
00342 return StatusCode::SUCCESS;
00343 }