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 <G4ParticleTable.hh>
16 #include <G4UImanager.hh>
17 #include <G4AffineTransform.hh>
18 #include <G4TransportationManager.hh>
19 #include <G4Navigator.hh>
21 #include <Randomize.hh>
23 #include <TLorentzVector.h>
25 TG4StepManager* TG4StepManager::fgInstance = 0;
27 TG4StepManager::TG4StepManager()
30 fStepStatus(kNormalStep),
35 TG4Globals::Exception(
36 "TG4StepManager: attempt to create two instances of singleton.");
42 TG4StepManager::TG4StepManager(const TG4StepManager& right) {
44 TG4Globals::Exception(
45 "Attempt to copy TG4StepManager singleton.");
48 TG4StepManager::~TG4StepManager() {
54 TG4StepManager& TG4StepManager::operator=(const TG4StepManager& right)
56 // check assignement to self
57 if (this == &right) return *this;
59 TG4Globals::Exception(
60 "Attempt to assign TG4StepManager singleton.");
67 void TG4StepManager::CheckTrack() const
69 // Gives exception in case the track is not defined.
73 TG4Globals::Exception("TG4StepManager: Track is not defined.");
77 void TG4StepManager::CheckStep() const
79 // Gives exception in case the step is not defined.
83 TG4Globals::Exception("TG4StepManager: Step is not defined.");
87 void TG4StepManager::CheckSteppingManager() const
89 // Gives exception in case the step is not defined.
92 if (!fSteppingManager)
93 TG4Globals::Exception("TG4StepManager: Stepping manager is not defined.");
97 void TG4StepManager::SetTLorentzVector(G4ThreeVector xyz, G4double t,
98 TLorentzVector& lv) const
100 // Fills TLorentzVector with G4ThreeVector and G4double.
109 G4VPhysicalVolume* TG4StepManager::GetCurrentOffPhysicalVolume(G4int off) const
111 // Returns the physical volume of the off-th mother's
112 // of the current volume.
115 G4VPhysicalVolume* physVolume = GetCurrentPhysicalVolume();
117 G4VPhysicalVolume* mother = physVolume;
120 if (mother) mother = mother->GetMother();
125 G4String text = "TG4StepManager::CurrentVolOff: \n";
126 text = text + " Volume ";
127 text = text + physVolume->GetName();
128 text = text + " has not defined mother in the required level.";
129 TG4Globals::Warning(text);
135 G4int TG4StepManager::GetVolumeID(G4VPhysicalVolume* physVolume) const
137 // Returns the sensitive detector ID of the specified
141 // sensitive detector ID
142 G4VSensitiveDetector* sd
143 = physVolume->GetLogicalVolume()->GetSensitiveDetector();
145 TG4VSensitiveDetector* tsd = dynamic_cast<TG4VSensitiveDetector*>(sd);
149 TG4Globals::Exception(
150 "TG4StepManager::GetVolumeID: Unknown sensitive detector type");
155 G4String text = "TG4StepManager::GetVolumeID: \n";
156 text = text + " Volume " + physVolume->GetName();
157 text = text + " has not a sensitive detector.";
158 //TG4Globals::Exception(text);
159 TG4Globals::Warning(text);
167 void TG4StepManager::StopTrack()
169 // Stops the current track and skips to the next.
170 // ?? do we want to invoke rest processes?
171 // ?? do we want to stop secondaries too?
172 // possible "stop" track status from G4:
173 // fStopButAlive, // Invoke active rest physics processes and
174 // // and kill the current track afterward
175 // fStopAndKill, // Kill the current track
176 // fKillTrackAndSecondaries,
177 // // Kill the current track and also associated
183 fTrack->SetTrackStatus(fStopAndKill);
184 // fTrack->SetTrackStatus(fStopButAlive);
185 // fTrack->SetTrackStatus(fKillTrackAndSecondaries);
188 void TG4StepManager::StopEvent()
190 // Aborts the current event processing.
195 fTrack->SetTrackStatus(fKillTrackAndSecondaries);
196 //StopTrack(); // cannot be used as it keeps secondaries
197 G4UImanager::GetUIpointer()->ApplyCommand("/event/abort");
198 G4UImanager::GetUIpointer()->ApplyCommand("/alStacking/clearStack");
201 void TG4StepManager::Rndm(Float_t* array, const Int_t size) const
203 // Random numbers array of the specified size.
206 G4double* const kpDoubleArray = new G4double[size];
207 RandFlat::shootArray(size, kpDoubleArray);
208 for (G4int i=0; i<size; i++) {
209 array[i] = kpDoubleArray[i];
211 delete [] kpDoubleArray;
214 void TG4StepManager::SetMaxStep(Float_t step)
216 // Maximum step allowed in the current logical volume.
217 // The maximum value is kept for following tracks - is it ok ??
221 G4LogicalVolume* curLogVolume
222 = GetCurrentPhysicalVolume()->GetLogicalVolume();
223 G4UserLimits* userLimits
224 = curLogVolume->GetUserLimits();
225 if (userLimits == 0) {
226 userLimits = new G4UserLimits(step);
227 curLogVolume->SetUserLimits(userLimits);
230 userLimits->SetMaxAllowedStep(step);
233 void TG4StepManager::SetMaxNStep(Int_t maxNofSteps)
235 // Not yet implemented.
239 "TG4StepManager::SetMaxNStep(..) is not yet implemented.");
242 void TG4StepManager::SetUserDecay(Int_t pdg)
244 // Not yet implemented.
247 TG4Globals::Exception(
248 "TG4StepManager::SetUserDecay(..) is not yet implemented.");
251 G4VPhysicalVolume* TG4StepManager::GetCurrentPhysicalVolume() const
253 // Returns the current physical volume.
254 // According to fStepStatus the volume from track vertex,
255 // pre step point or post step point is returned.
258 G4VPhysicalVolume* physVolume;
259 if (fStepStatus == kNormalStep) {
261 physVolume = fStep->GetPreStepPoint()->GetPhysicalVolume();
263 else if (fStepStatus == kBoundary) {
265 physVolume = fStep->GetPostStepPoint()->GetPhysicalVolume();
269 G4ThreeVector position = fTrack->GetPosition();
270 G4Navigator* navigator =
271 G4TransportationManager::GetTransportationManager()->
272 GetNavigatorForTracking();
274 = navigator->LocateGlobalPointAndSetup(position);
280 Int_t TG4StepManager::CurrentVolID(Int_t& copyNo) const
282 // Returns the current sensitive detector ID
283 // and the copy number of the current physical volume.
286 G4VPhysicalVolume* physVolume = GetCurrentPhysicalVolume();
287 copyNo = physVolume->GetCopyNo();
289 // sensitive detector ID
290 return GetVolumeID(physVolume);
293 Int_t TG4StepManager::CurrentVolOffID(Int_t off, Int_t& copyNo) const
295 // Returns the off-th mother's of the current volume
296 // the sensitive detector ID and the copy number.
299 if (off == 0) return CurrentVolID(copyNo);
301 G4VPhysicalVolume* mother = GetCurrentOffPhysicalVolume(off);
304 copyNo = mother->GetCopyNo();
306 // sensitive detector ID
307 return GetVolumeID(mother);
315 const char* TG4StepManager::CurrentVolName() const
317 // Returns the current physical volume name.
320 return GetCurrentPhysicalVolume()->GetName();
323 const char* TG4StepManager::CurrentVolOffName(Int_t off) const
325 // Returns the off-th mother's physical volume name.
328 if (off == 0) return CurrentVolName();
330 G4VPhysicalVolume* mother = GetCurrentOffPhysicalVolume(off);
333 return mother->GetName();
338 Int_t TG4StepManager::CurrentMaterial(Float_t &a, Float_t &z, Float_t &dens,
339 Float_t &radl, Float_t &absl) const
341 // Returns the parameters of the current material during transport
342 // the return value is the number of elements in the mixture.
345 G4VPhysicalVolume* physVolume = GetCurrentPhysicalVolume();
348 = physVolume->GetLogicalVolume()->GetMaterial();
350 // this if may be redundant - check
353 G4int nofElements = material->GetNumberOfElements();
354 TG4GeometryManager* pGeometryManager = TG4GeometryManager::Instance();
355 a = pGeometryManager->GetEffA(material);
356 z = pGeometryManager->GetEffZ(material);
359 dens = material->GetDensity();
360 dens /= TG3Units::MassDensity();
363 radl = material->GetRadlen();
364 radl /= TG3Units::Length();
366 absl = 0.; // this parameter is not defined in Geant4
370 TG4Globals::Exception(
371 "TG4StepManager::CurrentMaterial(..): material is not defined.");
376 void TG4StepManager::Gmtod(Float_t* xm, Float_t* xd, Int_t iflag)
378 // Transforms a position from the world reference frame
379 // to the current volume reference frame.
381 // Geant3 desription:
382 // ==================
383 // Computes coordinates XD (in DRS)
384 // from known coordinates XM in MRS
385 // The local reference system can be initialized by
386 // - the tracking routines and GMTOD used in GUSTEP
387 // - a call to GMEDIA(XM,NUMED)
388 // - a call to GLVOLU(NLEVEL,NAMES,NUMBER,IER)
389 // (inverse routine is GDTOM)
391 // If IFLAG=1 convert coordinates
392 // IFLAG=2 convert direction cosinus
398 G4ThreeVector theGlobalPoint(xm[0],xm[1],xm[2]);
400 //const G4NavigationHistory* history
401 // = fStep->GetPreStepPoint()->GetTouchable()->GetHistory();
402 G4AffineTransform affineTransform
403 = fStep->GetPreStepPoint()->GetTouchable()->GetHistory()
406 G4ThreeVector theLocalPoint;
408 theLocalPoint = affineTransform.TransformPoint(theGlobalPoint);
409 else if ( iflag == 2)
410 theLocalPoint = affineTransform.TransformAxis(theGlobalPoint);
412 TG4Globals::Exception(
413 "TG4StepManager::Gmtod(..,iflag): iflag is not in 1..2");
415 xd[0] = theLocalPoint.x();
416 xd[1] = theLocalPoint.y();
417 xd[2] = theLocalPoint.z();
421 G4ThreeVector direction(0,0,0);
422 G4bool RelativeSearch = true;
423 G4Navigator* theNavigator =
424 G4TransportationManager::GetTransportationManager()->
425 GetNavigatorForTracking();
427 G4VPhysicalVolume* pPhysVol;
429 = LocateGlobalPointAndSetup(theGlobalPoint, &direction, RelativeSearch);
430 //LocateGlobalPointWithinVolume(theGlobalPoint);
433 = theNavigator->GetGlobalToLocalTransform();
437 void TG4StepManager::Gdtom(Float_t* xd, Float_t* xm, Int_t iflag)
439 // Transforms a position from the current volume reference frame
440 // to the world reference frame.
442 // Geant3 desription:
443 // ==================
444 // Computes coordinates XM (Master Reference System
445 // knowing the coordinates XD (Detector Ref System)
446 // The local reference system can be initialized by
447 // - the tracking routines and GDTOM used in GUSTEP
448 // - a call to GSCMED(NLEVEL,NAMES,NUMBER)
449 // (inverse routine is GMTOD)
451 // If IFLAG=1 convert coordinates
452 // IFLAG=2 convert direction cosinus
460 G4ThreeVector theLocalPoint(xd[0],xd[1],xd[2]);
462 G4AffineTransform affineTransform
463 = fStep->GetPreStepPoint()->GetTouchable()->GetHistory()
464 ->GetTopTransform().Inverse();
466 G4ThreeVector theGlobalPoint;
468 theGlobalPoint = affineTransform.TransformPoint(theLocalPoint);
470 theGlobalPoint = affineTransform.TransformAxis(theLocalPoint);
473 "TG4StepManager::Gdtom(...,iflag): iflag is not in 1..2");
475 xm[0] = theGlobalPoint.x();
476 xm[1] = theGlobalPoint.y();
477 xm[2] = theGlobalPoint.z();
480 Float_t TG4StepManager::MaxStep() const
482 // Returns maximum step allowed in the current logical volume
487 G4LogicalVolume* curLogVolume
488 = GetCurrentPhysicalVolume()->GetLogicalVolume();
489 G4UserLimits* userLimits
490 = curLogVolume->GetUserLimits();
493 if (userLimits == 0) {
494 G4String text = "User Limits are not defined for log volume ";
495 text = text + curLogVolume->GetName();
496 TG4Globals::Warning(text);
500 const G4Track& trackRef = *(fTrack);
501 maxStep = userLimits->GetMaxAllowedStep(trackRef);
502 maxStep /= TG3Units::Length();
507 Int_t TG4StepManager::GetMaxNStep() const
509 // Not yet implemented.
513 "Method GetMaxNStep is not yet implemented in TG4StepManager.");
517 void TG4StepManager::TrackPosition(TLorentzVector& position) const
519 // Current particle position (in the world reference frame)
520 // and the local time since the current track is created
521 // (position of the PostStepPoint).
527 // check if this is == to PostStepPoint position !!
528 G4ThreeVector positionVector = fTrack->GetPosition();
529 positionVector *= 1./(TG3Units::Length());
532 G4double time = fTrack->GetLocalTime();
533 time /= TG3Units::Time();
535 SetTLorentzVector(positionVector, time, position);
538 Int_t TG4StepManager::GetMedium() const
540 // Returns the second index of the current material (corresponding to
541 // G3 tracking medium index).
545 G4Material* curMaterial
546 = GetCurrentPhysicalVolume()->GetLogicalVolume()->GetMaterial();
549 TG4GeometryManager* pGeometryManager = TG4GeometryManager::Instance();
550 return pGeometryManager->GetMediumId(curMaterial);
553 void TG4StepManager::TrackMomentum(TLorentzVector& momentum) const
555 // Current particle "momentum" (px, py, pz, Etot).
560 G4ThreeVector momentumVector = fTrack->GetMomentum();
561 momentumVector *= 1./(TG3Units::Energy());
563 G4double energy = fTrack->GetDynamicParticle()->GetTotalEnergy();
564 energy /= TG3Units::Energy();
566 SetTLorentzVector(momentumVector, energy, momentum);
569 void TG4StepManager::TrackVertexPosition(TLorentzVector& position) const
571 // The vertex particle position (in the world reference frame)
572 // and the local time since the current track is created.
578 G4ThreeVector positionVector = fTrack->GetVertexPosition();
579 positionVector *= 1./(TG3Units::Length());
583 G4double time = fTrack->GetLocalTime();
584 time /= TG3Units::Time();
586 SetTLorentzVector(positionVector, time, position);
589 void TG4StepManager::TrackVertexMomentum(TLorentzVector& momentum) const
591 // The vertex particle "momentum" (px, py, pz, Ekin)
592 // to do: change Ekin -> Etot
596 G4ThreeVector momentumVector = fTrack->GetVertexMomentumDirection();
597 momentumVector *= 1./(TG3Units::Energy());
599 G4double energy = fTrack->GetVertexKineticEnergy();
600 energy /= TG3Units::Energy();
602 SetTLorentzVector(momentumVector, energy, momentum);
605 Float_t TG4StepManager::TrackStep() const
607 // Returns the current step length.
611 if (fStepStatus == kNormalStep) {
613 length = fStep->GetStepLength();
614 length /= TG3Units::Length();
622 Float_t TG4StepManager::TrackLength() const
624 // Returns the length of the current track from its origin.
629 G4double length = fTrack->GetTrackLength();
630 length /= TG3Units::Length();
634 Float_t TG4StepManager::TrackTime() const
636 // Returns the local time since the current track is created.
638 // in Geant4: there is also defined proper time as
639 // the proper time of the dynamical particle of the current track.
644 G4double time = fTrack->GetLocalTime();
645 time /= TG3Units::Time();
649 Float_t TG4StepManager::Edep() const
651 // Returns total energy deposit in this step.
654 G4double energyDeposit;
655 if (fStepStatus == kNormalStep) {
657 energyDeposit = fStep->GetTotalEnergyDeposit();
658 energyDeposit /= TG3Units::Energy();
663 return energyDeposit;
666 Int_t TG4StepManager::TrackPid() const
668 // Returns the current particle PDG encoding.
673 G4ParticleDefinition* particle
674 = fTrack->GetDynamicParticle()->GetDefinition();
676 // ask TG4PhysicsManager to get PDG encoding
677 // (in order to get PDG from extended TDatabasePDG
678 // in case the standard PDG code is not defined)
679 TG4PhysicsManager* pPhysicsManager = TG4PhysicsManager::Instance();
680 G4int pdgEncoding = pPhysicsManager->GetPDGEncodingFast(particle);
685 Float_t TG4StepManager::TrackCharge() const
687 // Returns the current particle charge.
692 = fTrack->GetDynamicParticle()->GetDefinition()
694 charge /= TG3Units::Charge();
698 Float_t TG4StepManager::TrackMass() const
700 // Returns current particle rest mass.
706 = fTrack->GetDynamicParticle()->GetDefinition()
708 mass /= TG3Units::Mass();
712 Float_t TG4StepManager::Etot() const
714 // Returns total energy of the current particle.
720 = fTrack->GetDynamicParticle()->GetTotalEnergy();
721 energy /= TG3Units::Energy();
725 Bool_t TG4StepManager::IsTrackInside() const
727 // Returns true if particle does not cross geometrical boundary
728 // and is not in vertex.
731 if (fStepStatus == kNormalStep && !(IsTrackExiting()) ) {
732 // track is always inside during a normal step
739 Bool_t TG4StepManager::IsTrackEntering() const
741 // Returns true if particle cross a geometrical boundary
745 if (fStepStatus != kNormalStep) {
746 // track is entering during a vertex or boundary step
753 Bool_t TG4StepManager::IsTrackExiting() const
755 // Returns true if particle cross a geometrical boundary.
758 if (fStepStatus == kNormalStep) {
761 if (fStep->GetPostStepPoint()->GetStepStatus() == fGeomBoundary)
768 Bool_t TG4StepManager::IsTrackOut() const
770 // Returns true if particle cross the world boundary
771 // at post-step point.
774 if (fStepStatus == kVertex) return false;
780 = fStep->GetPostStepPoint()->GetStepStatus();
781 if (status == fWorldBoundary)
787 Bool_t TG4StepManager::IsTrackStop() const
789 // Returns true if particle has stopped
790 // or has been killed, suspended or postponed to next event.
792 // Possible track status from G4:
793 // fAlive, // Continue the tracking
794 // fStopButAlive, // Invoke active rest physics processes and
795 // // and kill the current track afterward
796 // fStopAndKill, // Kill the current track
797 // fKillTrackAndSecondaries,
798 // // Kill the current track and also associated
800 // fSuspend, // Suspend the current track
801 // fPostponeToNextEvent
802 // // Postpones the tracking of thecurrent track
803 // // to the next event.
810 = fTrack->GetTrackStatus();
811 if ((status == fStopAndKill) ||
812 (status == fKillTrackAndSecondaries) ||
813 (status == fSuspend) ||
814 (status == fPostponeToNextEvent)) {
821 Bool_t TG4StepManager::IsTrackDisappeared() const
823 // Returns true if particle has disappeared
824 // (due to any physical process)
825 // or has been killed, suspended or postponed to next event.
832 = fTrack->GetTrackStatus();
833 if ((status == fStopButAlive) ||
834 (status == fKillTrackAndSecondaries) ||
835 (status == fSuspend) ||
836 (status == fPostponeToNextEvent)) {
843 Bool_t TG4StepManager::IsTrackAlive() const
845 // Returns true if particle continues tracking.
851 = fTrack->GetTrackStatus();
852 if (status == fAlive)
858 Bool_t TG4StepManager::IsNewTrack() const
860 // Returns true when track performs the first step.
863 if (fStepStatus == kVertex)
869 Int_t TG4StepManager::NSecondaries() const
871 // Returns the number of secondary particles generated
872 // in the current step.
875 CheckSteppingManager();
877 G4int nofSecondaries = 0;
878 nofSecondaries += fSteppingManager->GetfN2ndariesAtRestDoIt();
879 nofSecondaries += fSteppingManager->GetfN2ndariesAlongStepDoIt();
880 nofSecondaries += fSteppingManager->GetfN2ndariesPostStepDoIt();
882 return nofSecondaries;
885 void TG4StepManager::GetSecondary(Int_t index, Int_t& particleId,
886 TLorentzVector& position, TLorentzVector& momentum)
888 // Fills the parameters (particle encoding, position, momentum)
889 // of the generated secondary particle which is specified by index.
890 // !! Check if indexing of secondaries is same !!
893 CheckSteppingManager();
895 G4int nofSecondaries = NSecondaries();
896 G4TrackVector* secondaryTracks = fSteppingManager->GetSecondary();
898 if (secondaryTracks){
899 if (index < nofSecondaries) {
901 // the index of the first secondary of this step
903 = secondaryTracks->entries() - nofSecondaries;
904 // (the secondaryTracks vector contains secondaries
905 // produced by the track at previous steps, too)
907 = (*secondaryTracks)[startIndex + index];
911 = track->GetDynamicParticle()->GetDefinition()->GetPDGEncoding();
914 G4ThreeVector positionVector = track->GetPosition();
915 positionVector *= 1./(TG3Units::Length());
916 G4double time = track->GetLocalTime();
917 time /= TG3Units::Time();
918 SetTLorentzVector(positionVector, time, position);
921 G4ThreeVector momentumVector = track->GetMomentum();
922 G4double energy = track->GetDynamicParticle()->GetTotalEnergy();
923 energy /= TG3Units::Energy();
924 SetTLorentzVector(momentumVector, energy, momentum);
927 TG4Globals::Exception(
928 "TG4StepManager::GetSecondary(): wrong secondary track index.");
932 TG4Globals::Exception(
933 "TG4StepManager::GetSecondary(): secondary tracks vector is empty");
937 const char* TG4StepManager::ProdProcess() const
939 // Returns the name of the process that defined current step
940 // (and may produce the secondary particles).
945 const G4VProcess* curProcess
946 = fStep->GetPostStepPoint()->GetProcessDefinedStep();
948 G4String g4Name = curProcess->GetProcessName();