Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions docs/source_and_particle_management.rst
Original file line number Diff line number Diff line change
Expand Up @@ -822,7 +822,7 @@ Required commands
``/gate/source/NAME/setPositroniumLifetimes t1 t2 ... tn unit``
Lifetime of each component. The last token is a Geant4 time unit such as ``ns``.

``/gate/source/NAME/setPromptPhotonProbabilites p1 p2 ... pn``
``/gate/source/NAME/setPromptPhotonProbabilities p1 p2 ... pn``
Probability of prompt-gamma emission for each component. Values are restricted to the ``[0, 1]`` range by the messenger.

``/gate/source/NAME/setPromptPhotonEnergies e1 e2 ... en unit``
Expand Down Expand Up @@ -855,7 +855,7 @@ Optional commands

.. note::

The current implementation requires both ``setPromptPhotonProbabilites`` and ``setPromptPhotonEnergies`` even when the prompt-gamma probability is zero for all components. A common convention is to set the corresponding energies to ``0``.
The current implementation requires both ``setPromptPhotonProbabilities`` and ``setPromptPhotonEnergies`` even when the prompt-gamma probability is zero for all components. A common convention is to set the corresponding energies to ``0``.

Event timing and generated vertices
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down Expand Up @@ -958,7 +958,7 @@ The example below defines a two-component source with explicit 2-gamma and 3-gam
/gate/source/psSource/setPositroniumLifetimes 0.125 142.0 ns
/gate/source/psSource/setDecayKinds k2Gamma k3Gamma
/gate/source/psSource/setPositronInteractions kParaPs kOrthoPs
/gate/source/psSource/setPromptPhotonProbabilites 1.0 1.0
/gate/source/psSource/setPromptPhotonProbabilities 1.0 1.0
/gate/source/psSource/setPromptPhotonEnergies 1.274 1.274 MeV
/gate/source/psSource/setElectronCaptureProbabilities 0.0 0.0
/gate/source/psSource/setMeanPositronRange 0.2 0.2 mm
Expand Down
5 changes: 3 additions & 2 deletions source/digits_hits/src/GateDigitizerInitializationModule.cc
Original file line number Diff line number Diff line change
Expand Up @@ -135,14 +135,15 @@ void GateDigitizerInitializationModule::Digitize()

//-------------------------------------------------

// An empty volume name only means that the output module in use did not
// fill it, so it is replaced by the "NULL" placeholder. It tells nothing
// about the source of the event, hence sourceID is left untouched.
if ((*inHC)[i]->GetComptonVolumeName().empty()) {
Digi->SetComptonVolumeName( "NULL" );
Digi->SetSourceID( -1 );
}

if ((*inHC)[i]->GetRayleighVolumeName().empty()) {
Digi->SetRayleighVolumeName( "NULL" );
Digi->SetSourceID( -1 );
}

/* // if (nVerboseLevel>1)
Expand Down
1 change: 1 addition & 0 deletions source/digits_hits/src/GateHit.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ GateHit::GateHit()
m_PDGEncoding(0),
m_trackID(0),
m_parentID(0),
m_sourceID(-1),
m_systemID(-1),
m_sourceEnergy(-1),
m_sourcePDG(0),
Expand Down
5 changes: 3 additions & 2 deletions source/digits_hits/src/GateHitConvertor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -179,14 +179,15 @@ void GateHitConvertor::ProcessOneHit(const GateHit* hit,GatePulseList* pulseList



// An empty volume name only means that the output module in use did not fill it,
// so it is replaced by the "NULL" placeholder. It tells nothing about the source
// of the event, hence sourceID is left untouched.
if (hit->GetComptonVolumeName().empty()) {
pulse->SetComptonVolumeName( "NULL" );
pulse->SetSourceID( -1 );
}

if (hit->GetRayleighVolumeName().empty()) {
pulse->SetRayleighVolumeName( "NULL" );
pulse->SetSourceID( -1 );
}

if (nVerboseLevel>1)
Expand Down
28 changes: 26 additions & 2 deletions source/digits_hits/src/GateMultiPhotonAnalysis.cc
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,20 @@ void RunDigitizersIfNeeded() {
}
}

//! Runs the digitizer chain when the enclosing scope is left, whichever path is taken.
//! GateAnalysis calls the digitizer outside of its "no trajectory container" branch, so
//! whether Singles and Coincidences are produced for an event does not depend on the
//! analysis being able to process that event. The guard gives the same guarantee here,
//! where the event is abandoned in more than one place.
class ScopedDigitizerRunner {
public:
ScopedDigitizerRunner() = default;
~ScopedDigitizerRunner() { RunDigitizersIfNeeded(); }

ScopedDigitizerRunner(const ScopedDigitizerRunner &) = delete;
ScopedDigitizerRunner &operator=(const ScopedDigitizerRunner &) = delete;
};

} // namespace

GateMultiPhotonAnalysis::GateMultiPhotonAnalysis(const G4String &name, GateOutputMgr *outputMgr, DigiMode digiMode)
Expand Down Expand Up @@ -312,6 +326,18 @@ void GateMultiPhotonAnalysis::RecordEndOfEvent(const G4Event *event) {
return;
}

// From here on the event is digitized whatever happens to the analysis itself.
ScopedDigitizerRunner digitizerRunner;

// An event without any primary vertex carries no track, hence no hit and no trajectory
// container. GateSourceMgr stops generating vertices once the time limit of the run is
// reached, so the last event of every run looks exactly like this. There is nothing to
// analyse and nothing anomalous about it, so it is skipped quietly instead of being
// reported as a missing trajectory container.
if (event->GetNumberOfPrimaryVertex() == 0) {
return;
}

std::vector<GateHitsCollection *> CHC_vector = GetOutputMgr()->GetHitCollections();
GatePhantomHitsCollection *PHC = GetOutputMgr()->GetPhantomHitCollection();

Expand Down Expand Up @@ -375,8 +401,6 @@ void GateMultiPhotonAnalysis::RecordEndOfEvent(const G4Event *event) {
m_trajectoryNavigator);
ProcessTimeline(&timeline, m_trajectoryNavigator, context, legacyPhotonIDPolicy);
}

RunDigitizersIfNeeded();
}

void GateMultiPhotonAnalysis::RecordStepWithVolume(const GateVVolume *, const G4Step *) {
Expand Down
18 changes: 16 additions & 2 deletions source/digits_hits/src/GateToRoot.cc
Original file line number Diff line number Diff line change
Expand Up @@ -628,9 +628,17 @@ void GateToRoot::RecordEndOfAcquisition() {

// m_hfile = m_treeHit->GetCurrentFile();

// Get file only for the 1st tree as it is the same file for all trees
m_hfile = m_treesHit[0]->GetCurrentFile();
// Get file only for the 1st tree as it is the same file for all trees.
// The vector may be empty here: RecordEndOfRun() drops the trees (it saves the
// current file beforehand) and a setup without any sensitive detector never fills
// it. In both cases m_hfile already points to the file to be written.
if (!m_treesHit.empty() && m_treesHit[0])
m_hfile = m_treesHit[0]->GetCurrentFile();

if (!m_hfile) {
G4cerr << "GateToRoot::RecordEndOfAcquisition(): no ROOT file to write !\n";
return;
}

if (nVerboseLevel > 0)
G4cout << "GateToRoot: ROOT: files writing...\n";
Expand Down Expand Up @@ -686,6 +694,12 @@ void GateToRoot::RecordEndOfRun(const G4Run *) {

nbPrimaries -= 1.; // Number of primaries increase too much at each end of run !

// ROOT may have switched to another file while the run was written (files are split
// above 1.9 GBytes), so remember where the trees actually live before dropping them -
// RecordEndOfAcquisition() has no tree left to ask.
if (!m_treesHit.empty() && m_treesHit[0])
m_hfile = m_treesHit[0]->GetCurrentFile();

m_hitBuffers.clear();
m_treesHit.clear();
}
Expand Down
2 changes: 1 addition & 1 deletion source/physics/include/GatePositroniumSourceMessenger.hh
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class GatePositroniumSourceMessenger: public GateVSourceMessenger

std::unique_ptr<G4UIcmdWithAString> upCmdSetPositroniumFractions;
std::unique_ptr<G4UIcmdWithAString> upCmdSetPositroniumLifetimes;
std::unique_ptr<G4UIcmdWithAString> upCmdSetPromptPhotonProbabilites;
std::unique_ptr<G4UIcmdWithAString> upCmdSetPromptPhotonProbabilities;
std::unique_ptr<G4UIcmdWithAString> upCmdSetPromptPhotonEnergies;
std::unique_ptr<G4UIcmdWithAString> upCmdSetElectronCaptureProbabilities;
std::unique_ptr<G4UIcmdWithAString> upCmdSetDecayKinds;
Expand Down
2 changes: 1 addition & 1 deletion source/physics/src/GatePositroniumDecayParamsGenerator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ void GatePositroniumDecayParamsGenerator::validatePositroniumDecayParams(const P
GateError(
"GatePositroniumDecayParamsGenerator::generatePositroniumDecayParams: "
"number of provided parameters in Fractions, PromptGamma, Lifetimes, "
"Gamma Energies, Electron Capture Probabilites are not the same");
"Gamma Energies, Electron Capture Probabilities are not the same");
}
if (params.fPositronInteractions.empty())
GateWarning("PositroniumSource: setPositronInteractions was not called. "
Expand Down
4 changes: 2 additions & 2 deletions source/physics/src/GatePositroniumSourceMessenger.cc
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ void GatePositroniumSourceMessenger::InitCommands()
upCmdSetPositroniumLifetimes.reset(GetStringCmd( "setPositroniumLifetimes", "\"t1, t2, t3 .., tn t_unit\" - where ti corresponds to lifetime constants and t_unit is one of the Geant4 time units e.g. ns" ) );
upCmdSetDecayKinds.reset(GetStringCmd( "setDecayKinds", "\"k1, k2, k3 .., kn\" - where ki is k2Gamma or k3Gamma" ) );
upCmdSetPositronInteractions.reset(GetStringCmd( "setPositronInteractions", "\"k1, k2, k3 .., kn\" - where ki is kParaPs, kDirect or kOrthoPs, of a given element in vector of components. Used to properly recalculate intensities of the components from the theory" ) );
upCmdSetPromptPhotonProbabilites.reset(GetStringCmd( "setPromptPhotonProbabilites", "\"f1, f2, f3 .., fn\" - where fi in [0.0, 1.0] " ) );
upCmdSetPromptPhotonProbabilities.reset(GetStringCmd( "setPromptPhotonProbabilities", "\"f1, f2, f3 .., fn\" - where fi in [0.0, 1.0] " ) );
upCmdSetPromptPhotonEnergies.reset(GetStringCmd( "setPromptPhotonEnergies", "\"e1, e2, e3 .., en e_unit\" - where ei are energies and e_unit is one of the Geant4 energy units e.g. MeV" ) );
upCmdSetMeanPositronRange.reset(GetStringCmd( "setMeanPositronRange", "\"r1, r2, r3 .., rn r_unit\" - where ri are mean positron range and r_unit is one of the Geant 4 distance units e.g. mm " ) );
upCmdSetElectronCaptureProbabilities.reset(GetStringCmd( "setElectronCaptureProbabilities", "\"f1, f2, f3 .., fn\" - where fi in [0.0, 1.0] " ) );
Expand Down Expand Up @@ -123,7 +123,7 @@ void GatePositroniumSourceMessenger::SetNewValue(G4UIcommand *command, G4String
} else if (command == upCmdSetPositroniumLifetimes.get()) {
auto lifetimes = parseListOfParamsWithUnit(new_value);
fParamGenerator.SetPositroniumLifetimes(lifetimes);
} else if (command == upCmdSetPromptPhotonProbabilites.get()) {
} else if (command == upCmdSetPromptPhotonProbabilities.get()) {
std::vector<float> promptPhotonProb;
std::stringstream ss(new_value);
float prob;
Expand Down
Loading