4 // See the class description in the header file.
6 #include "TG4StepManager.h"
7 #include "TG4GeometryManager.h"
8 #include "TG4PhysicsManager.h"
9 #include "TG4VSensitiveDetector.h"
10 #include "TG4Globals.h"
13 #include <G4SteppingManager.hh>
14 #include <G4UserLimits.hh>
15 #include <G4UImanager.hh>
16 #include <G4AffineTransform.hh>
17 #include <G4TransportationManager.hh>
18 #include <G4Navigator.hh>
20 #include <Randomize.hh>
21 #include <TLorentzVector.h>
23 TG4StepManager* TG4StepManager::fgInstance = 0;
25 TG4StepManager::TG4StepManager()
28 fStepStatus(kNormalStep),
33 TG4Globals::Exception(
34 "TG4StepManager: attempt to create two instances of singleton.");
40 TG4StepManager::TG4StepManager(const TG4StepManager& right) {
42 TG4Globals::Exception(
43 "Attempt to copy TG4StepManager singleton.");
46 TG4StepManager::~TG4StepManager() {
52 TG4StepManager& TG4StepManager::operator=(const TG4StepManager& right)
54 // check assignement to self
55 if (this == &right) return *this;
57 TG4Globals::Exception(
58 "Attempt to assign TG4StepManager singleton.");
65 void TG4StepManager::CheckTrack() const
67 // Gives exception in case the track is not defined.
71 TG4Globals::Exception("TG4StepManager: Track is not defined.");
75 void TG4StepManager::CheckStep(const G4String& method) const
77 // Gives exception in case the step is not defined.
81 G4String text = "TG4StepManager::";
82 text = text + method + ": Step is not defined.";
83 TG4Globals::Exception(text);
88 void TG4StepManager::CheckSteppingManager() const
90 // Gives exception in case the step is not defined.
93 if (!fSteppingManager)
94 TG4Globals::Exception("TG4StepManager: Stepping manager is not defined.");
98 void TG4StepManager::SetTLorentzVector(G4ThreeVector xyz, G4double t,
99 TLorentzVector& lv) const
101 // Fills TLorentzVector with G4ThreeVector and G4double.
110 G4VPhysicalVolume* TG4StepManager::GetCurrentOffPhysicalVolume(G4int off) const
112 // Returns the physical volume of the off-th mother's
113 // of the current volume.
116 G4VPhysicalVolume* physVolume = GetCurrentPhysicalVolume();
118 G4VPhysicalVolume* mother = physVolume;
122 if (mother) mother = mother->GetMother();
127 G4String text = "TG4StepManager::CurrentVolOff: \n";
128 text = text + " Volume ";
129 text = text + physVolume->GetName();
130 text = text + " has not defined mother in the required level.";
131 TG4Globals::Warning(text);
137 G4int TG4StepManager::GetVolumeID(G4VPhysicalVolume* physVolume) const
139 // Returns the sensitive detector ID of the specified
143 // sensitive detector ID
144 G4VSensitiveDetector* sd
145 = physVolume->GetLogicalVolume()->GetSensitiveDetector();
147 TG4VSensitiveDetector* tsd = dynamic_cast<TG4VSensitiveDetector*>(sd);
151 TG4Globals::Exception(
152 "TG4StepManager::GetVolumeID: Unknown sensitive detector type");
157 G4String text = "TG4StepManager::GetVolumeID: \n";
158 text = text + " Volume " + physVolume->GetName();
159 text = text + " has not a sensitive detector.";
160 //TG4Globals::Exception(text);
161 TG4Globals::Warning(text);
169 void TG4StepManager::StopTrack()
171 // Stops the current track and skips to the next.
172 // ?? do we want to invoke rest processes?
173 // ?? do we want to stop secondaries too?
174 // possible "stop" track status from G4:
175 // fStopButAlive, // Invoke active rest physics processes and
176 // // and kill the current track afterward
177 // fStopAndKill, // Kill the current track
178 // fKillTrackAndSecondaries,
179 // // Kill the current track and also associated
187 fTrack->SetTrackStatus(fStopAndKill);
188 // fTrack->SetTrackStatus(fStopButAlive);
189 // fTrack->SetTrackStatus(fKillTrackAndSecondaries);
192 void TG4StepManager::StopEvent()
194 // Aborts the current event processing.
201 fTrack->SetTrackStatus(fKillTrackAndSecondaries);
202 //StopTrack(); // cannot be used as it keeps secondaries
203 G4UImanager::GetUIpointer()->ApplyCommand("/event/abort");
204 G4UImanager::GetUIpointer()->ApplyCommand("/alStacking/clearStack");
207 void TG4StepManager::Rndm(Float_t* array, const Int_t size) const
209 // Random numbers array of the specified size.
212 G4double* const kpDoubleArray = new G4double[size];
213 RandFlat::shootArray(size, kpDoubleArray);
214 for (G4int i=0; i<size; i++) {
215 array[i] = kpDoubleArray[i];
217 delete [] kpDoubleArray;
220 void TG4StepManager::SetMaxStep(Float_t step)
222 // Maximum step allowed in the current logical volume.
223 // The maximum value is kept for following tracks - is it ok ??
227 G4LogicalVolume* curLogVolume
228 = GetCurrentPhysicalVolume()->GetLogicalVolume();
229 G4UserLimits* userLimits
230 = curLogVolume->GetUserLimits();
231 if (userLimits == 0) {
232 userLimits = new G4UserLimits(step);
233 curLogVolume->SetUserLimits(userLimits);
236 userLimits->SetMaxAllowedStep(step);
239 void TG4StepManager::SetMaxNStep(Int_t maxNofSteps)
241 // Not yet implemented.
245 "TG4StepManager::SetMaxNStep(..) is not yet implemented.");
248 void TG4StepManager::SetUserDecay(Int_t pdg)
250 // Not yet implemented.
253 TG4Globals::Exception(
254 "TG4StepManager::SetUserDecay(..) is not yet implemented.");
257 G4VPhysicalVolume* TG4StepManager::GetCurrentPhysicalVolume() const
259 // Returns the current physical volume.
260 // According to fStepStatus the volume from track vertex,
261 // pre step point or post step point is returned.
264 G4VPhysicalVolume* physVolume;
265 if (fStepStatus == kNormalStep) {
268 CheckStep("GetCurrentPhysicalVolume");
271 physVolume = fStep->GetPreStepPoint()->GetPhysicalVolume();
273 else if (fStepStatus == kBoundary) {
276 CheckStep("GetCurrentPhysicalVolume");
279 physVolume = fStep->GetPostStepPoint()->GetPhysicalVolume();
287 G4ThreeVector position = fTrack->GetPosition();
288 G4Navigator* navigator =
289 G4TransportationManager::GetTransportationManager()->
290 GetNavigatorForTracking();
292 = navigator->LocateGlobalPointAndSetup(position);
298 Int_t TG4StepManager::CurrentVolID(Int_t& copyNo) const
300 // Returns the current sensitive detector ID
301 // and the copy number of the current physical volume.
304 G4VPhysicalVolume* physVolume = GetCurrentPhysicalVolume();
305 copyNo = physVolume->GetCopyNo() + 1;
307 // sensitive detector ID
308 return GetVolumeID(physVolume);
311 Int_t TG4StepManager::CurrentVolOffID(Int_t off, Int_t& copyNo) const
313 // Returns the off-th mother's of the current volume
314 // the sensitive detector ID and the copy number.
317 if (off == 0) return CurrentVolID(copyNo);
319 G4VPhysicalVolume* mother = GetCurrentOffPhysicalVolume(off);
322 copyNo = mother->GetCopyNo() + 1;
324 // sensitive detector ID
325 return GetVolumeID(mother);
333 const char* TG4StepManager::CurrentVolName() const
335 // Returns the current physical volume name.
338 return GetCurrentPhysicalVolume()->GetName();
341 const char* TG4StepManager::CurrentVolOffName(Int_t off) const
343 // Returns the off-th mother's physical volume name.
346 if (off == 0) return CurrentVolName();
348 G4VPhysicalVolume* mother = GetCurrentOffPhysicalVolume(off);
351 return mother->GetName();
356 Int_t TG4StepManager::CurrentMaterial(Float_t &a, Float_t &z, Float_t &dens,
357 Float_t &radl, Float_t &absl) const
359 // Returns the parameters of the current material during transport
360 // the return value is the number of elements in the mixture.
363 G4VPhysicalVolume* physVolume = GetCurrentPhysicalVolume();
366 = physVolume->GetLogicalVolume()->GetMaterial();
369 G4int nofElements = material->GetNumberOfElements();
370 TG4GeometryManager* pGeometryManager = TG4GeometryManager::Instance();
371 a = pGeometryManager->GetEffA(material);
372 z = pGeometryManager->GetEffZ(material);
375 dens = material->GetDensity();
376 dens /= TG3Units::MassDensity();
379 radl = material->GetRadlen();
380 radl /= TG3Units::Length();
382 absl = 0.; // this parameter is not defined in Geant4
386 TG4Globals::Exception(
387 "TG4StepManager::CurrentMaterial(..): material is not defined.");
392 void TG4StepManager::Gmtod(Float_t* xm, Float_t* xd, Int_t iflag)
394 // Transforms a position from the world reference frame
395 // to the current volume reference frame.
397 // Geant3 desription:
398 // ==================
399 // Computes coordinates XD (in DRS)
400 // from known coordinates XM in MRS
401 // The local reference system can be initialized by
402 // - the tracking routines and GMTOD used in GUSTEP
403 // - a call to GMEDIA(XM,NUMED)
404 // - a call to GLVOLU(NLEVEL,NAMES,NUMBER,IER)
405 // (inverse routine is GDTOM)
407 // If IFLAG=1 convert coordinates
408 // IFLAG=2 convert direction cosinus
412 G4AffineTransform affineTransform;
414 if (fStepStatus == kVertex) {
415 G4Navigator* navigator =
416 G4TransportationManager::GetTransportationManager()->
417 GetNavigatorForTracking();
419 affineTransform = navigator->GetGlobalToLocalTransform();
428 = fStep->GetPreStepPoint()->GetTouchable()->GetHistory()
432 G4ThreeVector theGlobalPoint(xm[0],xm[1],xm[2]);
433 G4ThreeVector theLocalPoint;
435 theLocalPoint = affineTransform.TransformPoint(theGlobalPoint);
436 else if ( iflag == 2)
437 theLocalPoint = affineTransform.TransformAxis(theGlobalPoint);
439 TG4Globals::Exception(
440 "TG4StepManager::Gmtod(..,iflag): iflag is not in 1..2");
442 xd[0] = theLocalPoint.x();
443 xd[1] = theLocalPoint.y();
444 xd[2] = theLocalPoint.z();
447 void TG4StepManager::Gdtom(Float_t* xd, Float_t* xm, Int_t iflag)
449 // Transforms a position from the current volume reference frame
450 // to the world reference frame.
452 // Geant3 desription:
453 // ==================
454 // Computes coordinates XM (Master Reference System
455 // knowing the coordinates XD (Detector Ref System)
456 // The local reference system can be initialized by
457 // - the tracking routines and GDTOM used in GUSTEP
458 // - a call to GSCMED(NLEVEL,NAMES,NUMBER)
459 // (inverse routine is GMTOD)
461 // If IFLAG=1 convert coordinates
462 // IFLAG=2 convert direction cosinus
466 G4AffineTransform affineTransform;
468 if (fStepStatus == kVertex) {
469 G4Navigator* navigator =
470 G4TransportationManager::GetTransportationManager()->
471 GetNavigatorForTracking();
473 affineTransform = navigator->GetLocalToGlobalTransform();
484 = fStep->GetPreStepPoint()->GetTouchable()->GetHistory()
485 ->GetTopTransform().Inverse();
488 G4ThreeVector theLocalPoint(xd[0],xd[1],xd[2]);
489 G4ThreeVector theGlobalPoint;
491 theGlobalPoint = affineTransform.TransformPoint(theLocalPoint);
493 theGlobalPoint = affineTransform.TransformAxis(theLocalPoint);
496 "TG4StepManager::Gdtom(...,iflag): iflag is not in 1..2");
498 xm[0] = theGlobalPoint.x();
499 xm[1] = theGlobalPoint.y();
500 xm[2] = theGlobalPoint.z();
503 Float_t TG4StepManager::MaxStep() const
505 // Returns maximum step allowed in the current logical volume
509 G4LogicalVolume* curLogVolume
510 = GetCurrentPhysicalVolume()->GetLogicalVolume();
513 G4UserLimits* userLimits
514 = curLogVolume->GetUserLimits();
517 if (userLimits == 0) {
518 G4String text = "User Limits are not defined for log volume ";
519 text = text + curLogVolume->GetName();
520 TG4Globals::Warning(text);
524 const G4Track& trackRef = *(fTrack);
525 maxStep = userLimits->GetMaxAllowedStep(trackRef);
526 maxStep /= TG3Units::Length();
531 Int_t TG4StepManager::GetMaxNStep() const
533 // Not yet implemented.
537 "Method GetMaxNStep is not yet implemented in TG4StepManager.");
541 void TG4StepManager::TrackPosition(TLorentzVector& position) const
543 // Current particle position (in the world reference frame)
544 // and the local time since the current track is created
545 // (position of the PostStepPoint).
553 // check if this is == to PostStepPoint position !!
554 G4ThreeVector positionVector = fTrack->GetPosition();
555 positionVector *= 1./(TG3Units::Length());
558 G4double time = fTrack->GetLocalTime();
559 time /= TG3Units::Time();
561 SetTLorentzVector(positionVector, time, position);
564 Int_t TG4StepManager::GetMedium() const
566 // Returns the second index of the current material (corresponding to
567 // G3 tracking medium index).
571 G4Material* curMaterial
572 = GetCurrentPhysicalVolume()->GetLogicalVolume()->GetMaterial();
575 TG4GeometryManager* pGeometryManager = TG4GeometryManager::Instance();
576 return pGeometryManager->GetMediumId(curMaterial);
579 void TG4StepManager::TrackMomentum(TLorentzVector& momentum) const
581 // Current particle "momentum" (px, py, pz, Etot).
588 G4ThreeVector momentumVector = fTrack->GetMomentum();
589 momentumVector *= 1./(TG3Units::Energy());
591 G4double energy = fTrack->GetDynamicParticle()->GetTotalEnergy();
592 energy /= TG3Units::Energy();
594 SetTLorentzVector(momentumVector, energy, momentum);
597 void TG4StepManager::TrackVertexPosition(TLorentzVector& position) const
599 // The vertex particle position (in the world reference frame)
600 // and the local time since the current track is created.
608 G4ThreeVector positionVector = fTrack->GetVertexPosition();
609 positionVector *= 1./(TG3Units::Length());
613 G4double time = fTrack->GetLocalTime();
614 time /= TG3Units::Time();
616 SetTLorentzVector(positionVector, time, position);
619 void TG4StepManager::TrackVertexMomentum(TLorentzVector& momentum) const
621 // The vertex particle "momentum" (px, py, pz, Ekin)
622 // to do: change Ekin -> Etot
629 G4ThreeVector momentumVector = fTrack->GetVertexMomentumDirection();
630 momentumVector *= 1./(TG3Units::Energy());
632 G4double energy = fTrack->GetVertexKineticEnergy();
633 energy /= TG3Units::Energy();
635 SetTLorentzVector(momentumVector, energy, momentum);
638 Float_t TG4StepManager::TrackStep() const
640 // Returns the current step length.
644 if (fStepStatus == kNormalStep) {
647 CheckStep("TrackStep");
650 length = fStep->GetStepLength();
651 length /= TG3Units::Length();
659 Float_t TG4StepManager::TrackLength() const
661 // Returns the length of the current track from its origin.
668 G4double length = fTrack->GetTrackLength();
669 length /= TG3Units::Length();
673 Float_t TG4StepManager::TrackTime() const
675 // Returns the local time since the current track is created.
677 // in Geant4: there is also defined proper time as
678 // the proper time of the dynamical particle of the current track.
685 G4double time = fTrack->GetLocalTime();
686 time /= TG3Units::Time();
690 Float_t TG4StepManager::Edep() const
692 // Returns total energy deposit in this step.
695 G4double energyDeposit;
696 if (fStepStatus == kNormalStep) {
702 energyDeposit = fStep->GetTotalEnergyDeposit();
703 energyDeposit /= TG3Units::Energy();
708 return energyDeposit;
711 Int_t TG4StepManager::TrackPid() const
713 // Returns the current particle PDG encoding.
720 G4ParticleDefinition* particle
721 = fTrack->GetDynamicParticle()->GetDefinition();
723 // ask TG4PhysicsManager to get PDG encoding
724 // (in order to get PDG from extended TDatabasePDG
725 // in case the standard PDG code is not defined)
726 TG4PhysicsManager* pPhysicsManager = TG4PhysicsManager::Instance();
727 G4int pdgEncoding = pPhysicsManager->GetPDGEncodingFast(particle);
732 Float_t TG4StepManager::TrackCharge() const
734 // Returns the current particle charge.
742 = fTrack->GetDynamicParticle()->GetDefinition()
744 charge /= TG3Units::Charge();
748 Float_t TG4StepManager::TrackMass() const
750 // Returns current particle rest mass.
758 = fTrack->GetDynamicParticle()->GetDefinition()
760 mass /= TG3Units::Mass();
764 Float_t TG4StepManager::Etot() const
766 // Returns total energy of the current particle.
774 = fTrack->GetDynamicParticle()->GetTotalEnergy();
775 energy /= TG3Units::Energy();
779 Bool_t TG4StepManager::IsTrackInside() const
781 // Returns true if particle does not cross geometrical boundary
782 // and is not in vertex.
785 if (fStepStatus == kNormalStep && !(IsTrackExiting()) ) {
786 // track is always inside during a normal step
793 Bool_t TG4StepManager::IsTrackEntering() const
795 // Returns true if particle cross a geometrical boundary
799 if (fStepStatus != kNormalStep) {
800 // track is entering during a vertex or boundary step
807 Bool_t TG4StepManager::IsTrackExiting() const
809 // Returns true if particle cross a geometrical boundary.
812 if (fStepStatus == kNormalStep) {
815 CheckStep("IsTrackExiting");
818 if (fStep->GetPostStepPoint()->GetStepStatus() == fGeomBoundary)
825 Bool_t TG4StepManager::IsTrackOut() const
827 // Returns true if particle cross the world boundary
828 // at post-step point.
831 if (fStepStatus == kVertex) return false;
834 CheckStep("IsTrackCut");
839 = fStep->GetPostStepPoint()->GetStepStatus();
840 if (status == fWorldBoundary)
846 Bool_t TG4StepManager::IsTrackStop() const
848 // Returns true if particle has stopped
849 // or has been killed, suspended or postponed to next event.
851 // Possible track status from G4:
852 // fAlive, // Continue the tracking
853 // fStopButAlive, // Invoke active rest physics processes and
854 // // and kill the current track afterward
855 // fStopAndKill, // Kill the current track
856 // fKillTrackAndSecondaries,
857 // // Kill the current track and also associated
859 // fSuspend, // Suspend the current track
860 // fPostponeToNextEvent
861 // // Postpones the tracking of thecurrent track
862 // // to the next event.
871 = fTrack->GetTrackStatus();
872 if ((status == fStopAndKill) ||
873 (status == fKillTrackAndSecondaries) ||
874 (status == fSuspend) ||
875 (status == fPostponeToNextEvent)) {
882 Bool_t TG4StepManager::IsTrackDisappeared() const
884 // Returns true if particle has disappeared
885 // (due to any physical process)
886 // or has been killed, suspended or postponed to next event.
895 = fTrack->GetTrackStatus();
896 if ((status == fStopButAlive) ||
897 (status == fKillTrackAndSecondaries) ||
898 (status == fSuspend) ||
899 (status == fPostponeToNextEvent)) {
906 Bool_t TG4StepManager::IsTrackAlive() const
908 // Returns true if particle continues tracking.
916 = fTrack->GetTrackStatus();
917 if (status == fAlive)
923 Bool_t TG4StepManager::IsNewTrack() const
925 // Returns true when track performs the first step.
928 if (fStepStatus == kVertex)
934 Int_t TG4StepManager::NSecondaries() const
936 // Returns the number of secondary particles generated
937 // in the current step.
941 CheckSteppingManager();
944 G4int nofSecondaries = 0;
945 nofSecondaries += fSteppingManager->GetfN2ndariesAtRestDoIt();
946 nofSecondaries += fSteppingManager->GetfN2ndariesAlongStepDoIt();
947 nofSecondaries += fSteppingManager->GetfN2ndariesPostStepDoIt();
949 return nofSecondaries;
952 void TG4StepManager::GetSecondary(Int_t index, Int_t& particleId,
953 TLorentzVector& position, TLorentzVector& momentum)
955 // Fills the parameters (particle encoding, position, momentum)
956 // of the generated secondary particle which is specified by index.
957 // !! Check if indexing of secondaries is same !!
961 CheckSteppingManager();
964 G4int nofSecondaries = NSecondaries();
965 G4TrackVector* secondaryTracks = fSteppingManager->GetSecondary();
967 if (secondaryTracks){
968 if (index < nofSecondaries) {
970 // the index of the first secondary of this step
972 = secondaryTracks->entries() - nofSecondaries;
973 // (the secondaryTracks vector contains secondaries
974 // produced by the track at previous steps, too)
976 = (*secondaryTracks)[startIndex + index];
980 = track->GetDynamicParticle()->GetDefinition()->GetPDGEncoding();
983 G4ThreeVector positionVector = track->GetPosition();
984 positionVector *= 1./(TG3Units::Length());
985 G4double time = track->GetLocalTime();
986 time /= TG3Units::Time();
987 SetTLorentzVector(positionVector, time, position);
990 G4ThreeVector momentumVector = track->GetMomentum();
991 G4double energy = track->GetDynamicParticle()->GetTotalEnergy();
992 energy /= TG3Units::Energy();
993 SetTLorentzVector(momentumVector, energy, momentum);
996 TG4Globals::Exception(
997 "TG4StepManager::GetSecondary(): wrong secondary track index.");
1001 TG4Globals::Exception(
1002 "TG4StepManager::GetSecondary(): secondary tracks vector is empty");
1006 const char* TG4StepManager::ProdProcess() const
1008 // Returns the name of the process that defined current step
1009 // (and may produce the secondary particles).
1012 if (fStepStatus == kVertex) return "NONE";
1014 G4int nofSecondaries = NSecondaries();
1015 if (nofSecondaries == 0) return "NONE";
1017 #ifdef TGEANT4_DEBUG
1018 CheckStep("ProdProcess");
1021 const G4VProcess* curProcess
1022 = fStep->GetPostStepPoint()->GetProcessDefinedStep();
1024 G4String g4Name = curProcess->GetProcessName();