00001 #include "SimG4CMS/Muon/interface/MuonSensitiveDetector.h"
00002 #include "SimG4CMS/Muon/interface/MuonSlaveSD.h"
00003 #include "SimG4CMS/Muon//interface/MuonEndcapFrameRotation.h"
00004 #include "SimG4CMS/Muon/interface/MuonRpcFrameRotation.h"
00005 #include "Geometry/MuonNumbering/interface/MuonSubDetector.h"
00006
00007 #include "DataFormats/GeometryVector/interface/LocalVector.h"
00008
00009 #include "SimG4CMS/Muon/interface/SimHitPrinter.h"
00010 #include "SimDataFormats/TrackingHit/interface/UpdatablePSimHit.h"
00011
00012 #include "SimG4CMS/Muon/interface/MuonG4Numbering.h"
00013 #include "Geometry/MuonNumbering/interface/MuonBaseNumber.h"
00014 #include "Geometry/MuonNumbering/interface/MuonSimHitNumberingScheme.h"
00015
00016 #include "SimG4Core/Notification/interface/TrackInformation.h"
00017 #include "SimG4Core/Notification/interface/G4TrackToParticleID.h"
00018 #include "SimG4Core/Physics/interface/G4ProcessTypeEnumerator.h"
00019
00020 #include "G4SDManager.hh"
00021 #include "G4VProcess.hh"
00022 #include "G4EventManager.hh"
00023
00024 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00025
00026 #include <iostream>
00027
00028
00029 MuonSensitiveDetector::MuonSensitiveDetector(std::string name,
00030 const DDCompactView & cpv,
00031 SensitiveDetectorCatalog & clg,
00032 edm::ParameterSet const & p,
00033 const SimTrackManager* manager)
00034 : SensitiveTkDetector(name, cpv, clg, p),
00035 thePV(0), theHit(0), theDetUnitId(0), theTrackID(0), theManager(manager)
00036 {
00037 edm::ParameterSet m_MuonSD = p.getParameter<edm::ParameterSet>("MuonSD");
00038 STenergyPersistentCut = m_MuonSD.getParameter<double>("EnergyThresholdForPersistency");
00039 STallMuonsPersistent = m_MuonSD.getParameter<bool>("AllMuonsPersistent");
00040 printHits = m_MuonSD.getParameter<bool>("PrintHits");
00041
00042
00043
00044
00045
00046 LogDebug("MuonSimDebug") << "create MuonSubDetector "<<name<<std::endl;
00047
00048 detector = new MuonSubDetector(name);
00049
00050 LogDebug("MuonSimDebug") << "create MuonFrameRotation"<<std::endl;
00051
00052 if (detector->isEndcap()) {
00053
00054 theRotation=new MuonEndcapFrameRotation();
00055 } else if (detector->isRpc()) {
00056
00057 theRotation=new MuonRpcFrameRotation( cpv );
00058 } else {
00059 theRotation = 0;
00060 }
00061 LogDebug("MuonSimDebug") << "create MuonSlaveSD"<<std::endl;
00062 slaveMuon = new MuonSlaveSD(detector,theManager);
00063 LogDebug("MuonSimDebug") << "create MuonSimHitNumberingScheme"<<std::endl;
00064 numbering = new MuonSimHitNumberingScheme(detector, cpv);
00065 g4numbering = new MuonG4Numbering(cpv);
00066
00067
00068
00069
00070
00071 std::vector<std::string> lvNames = clg.logicalNames(name);
00072 this->Register();
00073 for (std::vector<std::string>::iterator it = lvNames.begin(); it != lvNames.end(); it++){
00074 LogDebug("MuonSimDebug") << name << " MuonSensitiveDetector:: attaching SD to LV " << *it << std::endl;
00075 this->AssignSD(*it);
00076 }
00077
00078 if (printHits) {
00079 thePrinter = new SimHitPrinter("HitPositionOSCAR.dat");
00080 }
00081
00082
00083 LogDebug("MuonSimDebug") << " EnergyThresholdForPersistency " << STenergyPersistentCut << " AllMuonsPersistent " << STallMuonsPersistent << std::endl;
00084
00085 theG4ProcessTypeEnumerator = new G4ProcessTypeEnumerator;
00086 myG4TrackToParticleID = new G4TrackToParticleID;
00087
00088 }
00089
00090
00091 MuonSensitiveDetector::~MuonSensitiveDetector() {
00092 delete g4numbering;
00093 delete numbering;
00094 delete slaveMuon;
00095 delete theRotation;
00096 delete detector;
00097
00098 delete theG4ProcessTypeEnumerator;
00099
00100 delete myG4TrackToParticleID;
00101 }
00102
00103 void MuonSensitiveDetector::update(const BeginOfEvent * i){
00104 clearHits();
00105
00106
00107 thePV = 0;
00108 theDetUnitId = 0;
00109 theTrackID = 0;
00110
00111 }
00112
00113 void MuonSensitiveDetector::update(const ::EndOfEvent * ev)
00114 {
00115
00116 }
00117
00118
00119 void MuonSensitiveDetector::clearHits()
00120 {
00121 LogDebug("MuonSimDebug") << "MuonSensitiveDetector::clearHits"<<std::endl;
00122 slaveMuon->Initialize();
00123 }
00124
00125 bool MuonSensitiveDetector::ProcessHits(G4Step * aStep, G4TouchableHistory * ROhist)
00126 {
00127 LogDebug("MuonSimDebug") <<" MuonSensitiveDetector::ProcessHits "<<InitialStepPosition(aStep,WorldCoordinates)<<std::endl;
00128
00129
00130
00131 if (aStep->GetTotalEnergyDeposit()>0.){
00132
00133 if( aStep->GetTrack()->GetDynamicParticle()->GetCharge() != 0 ){
00134
00135 if (newHit(aStep)) {
00136 saveHit();
00137 createHit(aStep);
00138 } else {
00139 updateHit(aStep);
00140 }
00141 return true;
00142 } else {
00143 storeVolumeAndTrack(aStep);
00144 return false;
00145 }
00146 }
00147 return false;
00148 }
00149
00150 uint32_t MuonSensitiveDetector::setDetUnitId(G4Step * aStep)
00151 {
00152
00153 MuonBaseNumber num = g4numbering->PhysicalVolumeToBaseNumber(aStep);
00154 return numbering->baseNumberToUnitNumber(num);
00155 }
00156
00157
00158 Local3DPoint MuonSensitiveDetector::toOrcaRef(Local3DPoint in ,G4Step * s){
00159 if (theRotation !=0 ) {
00160 return theRotation->transformPoint(in,s);
00161 }
00162 return (in);
00163 }
00164
00165 Local3DPoint MuonSensitiveDetector::toOrcaUnits(Local3DPoint in){
00166 return Local3DPoint(in.x()/cm,in.y()/cm,in.z()/cm);
00167 }
00168
00169 Global3DPoint MuonSensitiveDetector::toOrcaUnits(Global3DPoint in){
00170 return Global3DPoint(in.x()/cm,in.y()/cm,in.z()/cm);
00171 }
00172
00173 void MuonSensitiveDetector::storeVolumeAndTrack(G4Step * aStep)
00174 {
00175 G4VPhysicalVolume* pv = aStep->GetPreStepPoint()->GetPhysicalVolume();
00176 G4Track * t = aStep->GetTrack();
00177 thePV=pv;
00178 theTrackID=t->GetTrackID();
00179 }
00180
00181 bool MuonSensitiveDetector::newHit(G4Step * aStep){
00182
00183 G4VPhysicalVolume* pv = aStep->GetPreStepPoint()->GetPhysicalVolume();
00184 G4Track * t = aStep->GetTrack();
00185 uint32_t currentUnitId=setDetUnitId(aStep);
00186 unsigned int currentTrackID=t->GetTrackID();
00187
00188 bool changed=((pv!=thePV) ||
00189 (currentUnitId!=theDetUnitId) ||
00190 (currentTrackID!=theTrackID));
00191 return changed;
00192 }
00193
00194 void MuonSensitiveDetector::createHit(G4Step * aStep){
00195
00196 G4Track * theTrack = aStep->GetTrack();
00197
00198 Local3DPoint theEntryPoint;
00199 Local3DPoint theExitPoint;
00200
00201 if (detector->isBarrel()) {
00202 theEntryPoint= toOrcaUnits(toOrcaRef(InitialStepPositionVsParent(aStep,1),aStep));
00203 theExitPoint= toOrcaUnits(toOrcaRef(FinalStepPositionVsParent(aStep,1),aStep));
00204 } else if (detector->isEndcap()) {
00205
00206 theEntryPoint= toOrcaUnits(toOrcaRef(InitialStepPosition(aStep,LocalCoordinates),aStep));
00207 theExitPoint= toOrcaUnits(toOrcaRef(FinalStepPosition(aStep,LocalCoordinates),aStep));
00208 float zentry = theEntryPoint.z();
00209 float zexit = theExitPoint.z();
00210 Local3DPoint tempEntryPoint= toOrcaUnits(toOrcaRef(InitialStepPositionVsParent(aStep,4),aStep));
00211 Local3DPoint tempExitPoint= toOrcaUnits(toOrcaRef(FinalStepPositionVsParent(aStep,4),aStep));
00212
00213 theEntryPoint = Local3DPoint( tempEntryPoint.x(), tempEntryPoint.y(), zentry );
00214 theExitPoint = Local3DPoint( tempExitPoint.x(), tempExitPoint.y(), zexit );
00215 } else {
00216 theEntryPoint= toOrcaUnits(toOrcaRef(InitialStepPosition(aStep,LocalCoordinates),aStep));
00217 theExitPoint= toOrcaUnits(toOrcaRef(FinalStepPosition(aStep,LocalCoordinates),aStep));
00218 }
00219
00220 float thePabs = aStep->GetPreStepPoint()->GetMomentum().mag()/GeV;
00221 float theTof = aStep->GetPreStepPoint()->GetGlobalTime()/nanosecond;
00222 float theEnergyLoss = aStep->GetTotalEnergyDeposit()/GeV;
00223
00224 int theParticleType = myG4TrackToParticleID->particleID(theTrack);
00225 G4ThreeVector gmd = aStep->GetPreStepPoint()->GetMomentumDirection();
00226 G4ThreeVector lmd = ((G4TouchableHistory *)(aStep->GetPreStepPoint()->GetTouchable()))->GetHistory()
00227 ->GetTopTransform().TransformAxis(gmd);
00228 Local3DPoint lnmd = toOrcaRef(ConvertToLocal3DPoint(lmd),aStep);
00229 float theThetaAtEntry = lnmd.theta();
00230 float thePhiAtEntry = lnmd.phi();
00231
00232 storeVolumeAndTrack( aStep );
00233 theDetUnitId = setDetUnitId(aStep);
00234
00235 Global3DPoint theGlobalPos;
00236 if (printHits) {
00237 Local3DPoint theGlobalHelp = InitialStepPosition(aStep,WorldCoordinates);
00238 theGlobalEntry = toOrcaUnits(Global3DPoint (theGlobalHelp.x(),theGlobalHelp.y(),theGlobalHelp.z()));
00239
00240 G4StepPoint * preStepPoint = aStep->GetPreStepPoint();
00241 G4TouchableHistory * theTouchable=(G4TouchableHistory *)
00242 (preStepPoint->GetTouchable());
00243 theGlobalHelp=ConvertToLocal3DPoint(theTouchable->GetTranslation());
00244 theGlobalPos = toOrcaUnits(Global3DPoint (theGlobalHelp.x(),theGlobalHelp.y(),theGlobalHelp.z()));
00245
00246 }
00247
00248 LogDebug("MuonSimDebug") << "MuonSensitiveDetector::createHit UpdatablePSimHit"<<std::endl;
00249
00250 theHit = new UpdatablePSimHit(theEntryPoint,theExitPoint,thePabs,theTof,
00251 theEnergyLoss,theParticleType,theDetUnitId,
00252 theTrackID,theThetaAtEntry,thePhiAtEntry,
00253 theG4ProcessTypeEnumerator->processId(theTrack->GetCreatorProcess()));
00254
00255
00256 LogDebug("MuonSimDebug") <<"=== NEW ==================> ELOSS = "<<theEnergyLoss<<" "
00257 <<thePV->GetLogicalVolume()->GetName()<<std::endl;
00258 const G4VProcess* p = aStep->GetPostStepPoint()->GetProcessDefinedStep();
00259 const G4VProcess* p2 = aStep->GetPreStepPoint()->GetProcessDefinedStep();
00260 if (p)
00261 LogDebug("MuonSimDebug") <<" POST PROCESS = "<<p->GetProcessName()<<std::endl;
00262 if (p2)
00263 LogDebug("MuonSimDebug") <<" PRE PROCESS = "<<p2->GetProcessName()<<std::endl;
00264 LogDebug("MuonSimDebug") << "newhit theta " << theThetaAtEntry<<std::endl;
00265 LogDebug("MuonSimDebug") << "newhit phi " << thePhiAtEntry<<std::endl;
00266 LogDebug("MuonSimDebug") << "newhit pabs " << thePabs<<std::endl;
00267 LogDebug("MuonSimDebug") << "newhit tof " << theTof<<std::endl;
00268 LogDebug("MuonSimDebug") << "newhit track " << theTrackID<<std::endl;
00269 LogDebug("MuonSimDebug") << "newhit entry " << theEntryPoint<<std::endl;
00270 LogDebug("MuonSimDebug") << "newhit exit " << theExitPoint<<std::endl;
00271 LogDebug("MuonSimDebug") << "newhit eloss " << theEnergyLoss << std::endl;
00272 LogDebug("MuonSimDebug") << "newhit detid " << theDetUnitId<<std::endl;
00273 LogDebug("MuonSimDebug") << "newhit delta " << (theExitPoint-theEntryPoint)<<std::endl;
00274 LogDebug("MuonSimDebug") << "newhit deltu " << (theExitPoint-theEntryPoint).unit();
00275 LogDebug("MuonSimDebug") << " " << (theExitPoint-theEntryPoint).mag()<<std::endl;
00276 LogDebug("MuonSimDebug") << "newhit glob " << theGlobalEntry<<std::endl;
00277 LogDebug("MuonSimDebug") << "newhit dpos " << theGlobalPos<<std::endl;
00278 LogDebug("MuonSimDebug") << "newhit drot " << std::endl;
00279
00280
00281
00282
00283
00284
00285 int thePID = theTrack->GetDefinition()->GetPDGEncoding();
00286 LogDebug("MuonSimDebug") << " checking simtrack " << thePID << " " << thePabs << " STenergyPersistentCut " << STenergyPersistentCut << std::endl;
00287
00288 if( thePabs*GeV > STenergyPersistentCut
00289 || ( abs(thePID) == 13 && STallMuonsPersistent ) ){
00290 TrackInformation* info = getOrCreateTrackInformation(theTrack);
00291 LogDebug("MuonSimDebug") <<" track leaving hit in muons made selected for persistency"<<std::endl;
00292
00293 info->storeTrack(true);
00294 }
00295
00296 }
00297
00298 void MuonSensitiveDetector::updateHit(G4Step * aStep){
00299
00300
00301
00302
00303 Local3DPoint theExitPoint;
00304
00305 if (detector->isBarrel()) {
00306 theExitPoint= toOrcaUnits(toOrcaRef(FinalStepPositionVsParent(aStep,1),aStep));
00307 } else if (detector->isEndcap()) {
00308
00309 theExitPoint= toOrcaUnits(toOrcaRef(FinalStepPosition(aStep,LocalCoordinates),aStep));
00310 float zexit = theExitPoint.z();
00311 Local3DPoint tempExitPoint= toOrcaUnits(toOrcaRef(FinalStepPositionVsParent(aStep,4),aStep));
00312 theExitPoint = Local3DPoint( tempExitPoint.x(), tempExitPoint.y(), zexit );
00313 } else {
00314 theExitPoint= toOrcaUnits(toOrcaRef(FinalStepPosition(aStep,LocalCoordinates),aStep));
00315 }
00316
00317 float theEnergyLoss = aStep->GetTotalEnergyDeposit()/GeV;
00318
00319 if( theHit == 0 ){
00320 std::cerr << "!!ERRROR in MuonSensitiveDetector::updateHit. It is called when there is no hit " << std::endl;
00321 }
00322
00323 theHit->updateExitPoint(theExitPoint);
00324 theHit->addEnergyLoss(theEnergyLoss);
00325
00326 LogDebug("MuonSimDebug") <<"=== UPDATE ===============> ELOSS = "<<theEnergyLoss<<" "
00327 <<thePV->GetLogicalVolume()->GetName()<<std::endl;
00328 const G4VProcess* p = aStep->GetPostStepPoint()->GetProcessDefinedStep();
00329 const G4VProcess* p2 = aStep->GetPreStepPoint()->GetProcessDefinedStep();
00330 if (p)
00331 LogDebug("MuonSimDebug") <<" POST PROCESS = "<<p->GetProcessName()<<std::endl;
00332 if (p2)
00333 LogDebug("MuonSimDebug") <<" PRE PROCESS = "<<p2->GetProcessName()<<std::endl;
00334 LogDebug("MuonSimDebug") << "updhit exit " << theExitPoint<<std::endl;
00335 LogDebug("MuonSimDebug") << "updhit eloss " << theHit->energyLoss() <<std::endl;
00336 LogDebug("MuonSimDebug") << "updhit detid " << theDetUnitId<<std::endl;
00337 LogDebug("MuonSimDebug") << "updhit delta " << (theExitPoint-theHit->entryPoint())<<std::endl;
00338 LogDebug("MuonSimDebug") << "updhit deltu " << (theExitPoint-theHit->entryPoint()).unit();
00339 LogDebug("MuonSimDebug") << " " << (theExitPoint-theHit->entryPoint()).mag()<<std::endl;
00340
00341 }
00342
00343 void MuonSensitiveDetector::saveHit(){
00344
00345 if (theHit) {
00346 if (printHits) {
00347 thePrinter->startNewSimHit(detector->name());
00348 thePrinter->printId(theHit->detUnitId());
00349
00350
00351
00352 thePrinter->printLocal(theHit->entryPoint(),theHit->exitPoint());
00353 thePrinter->printGlobal(theGlobalEntry);
00354 }
00355 slaveMuon->processHits(*theHit);
00356
00357
00358 delete theHit;
00359 theHit = 0;
00360 }
00361
00362 }
00363
00364 TrackInformation* MuonSensitiveDetector::getOrCreateTrackInformation( const G4Track* gTrack)
00365 {
00366 G4VUserTrackInformation* temp = gTrack->GetUserInformation();
00367 if (temp == 0){
00368 std::cerr <<" ERROR: no G4VUserTrackInformation available"<<std::endl;
00369 abort();
00370 }else{
00371 TrackInformation* info = dynamic_cast<TrackInformation*>(temp);
00372 if (info ==0){
00373 std::cerr <<" ERROR: TkSimTrackSelection: the UserInformation does not appear to be a TrackInformation"<<std::endl;
00374 abort();
00375 }
00376 return info;
00377 }
00378 }
00379
00380 void MuonSensitiveDetector::EndOfEvent(G4HCofThisEvent*)
00381 {
00382
00383
00384 saveHit();
00385 }
00386
00387
00388 void MuonSensitiveDetector::fillHits(edm::PSimHitContainer& c, std::string n){
00389
00390
00391
00392
00393 if (slaveMuon->name() == n) c=slaveMuon->hits();
00394
00395 }
00396
00397 std::vector<std::string> MuonSensitiveDetector::getNames(){
00398 std::vector<std::string> temp;
00399 temp.push_back(slaveMuon->name());
00400 return temp;
00401 }
00402
00403 Local3DPoint MuonSensitiveDetector::InitialStepPositionVsParent(G4Step * currentStep, G4int levelsUp) {
00404
00405 G4StepPoint * preStepPoint = currentStep->GetPreStepPoint();
00406 G4ThreeVector globalCoordinates = preStepPoint->GetPosition();
00407
00408 G4TouchableHistory * theTouchable=(G4TouchableHistory *)
00409 (preStepPoint->GetTouchable());
00410
00411 G4int depth = theTouchable->GetHistory()->GetDepth();
00412 G4ThreeVector localCoordinates = theTouchable->GetHistory()
00413 ->GetTransform(depth-levelsUp).TransformPoint(globalCoordinates);
00414
00415 return ConvertToLocal3DPoint(localCoordinates);
00416 }
00417
00418 Local3DPoint MuonSensitiveDetector::FinalStepPositionVsParent(G4Step * currentStep, G4int levelsUp) {
00419
00420 G4StepPoint * postStepPoint = currentStep->GetPostStepPoint();
00421 G4StepPoint * preStepPoint = currentStep->GetPreStepPoint();
00422 G4ThreeVector globalCoordinates = postStepPoint->GetPosition();
00423
00424 G4TouchableHistory * theTouchable = (G4TouchableHistory *)
00425 (preStepPoint->GetTouchable());
00426
00427 G4int depth = theTouchable->GetHistory()->GetDepth();
00428 G4ThreeVector localCoordinates = theTouchable->GetHistory()
00429 ->GetTransform(depth-levelsUp).TransformPoint(globalCoordinates);
00430
00431 return ConvertToLocal3DPoint(localCoordinates);
00432 }