16#include "TRestDetectorElectronDiffusionProcess.h"
22TRestDetectorElectronDiffusionProcess::TRestDetectorElectronDiffusionProcess() {
Initialize(); }
24TRestDetectorElectronDiffusionProcess::TRestDetectorElectronDiffusionProcess(
const char* configFilename) {
31TRestDetectorElectronDiffusionProcess::~TRestDetectorElectronDiffusionProcess() {
delete fOutputHitsEvent; }
33void TRestDetectorElectronDiffusionProcess::LoadDefaultConfig() {
34 SetTitle(
"Default config");
36 fElectricField = 2000;
49 fTransversalDiffusionCoefficient = 0;
50 fLongitudinalDiffusionCoefficient = 0;
55 fInputHitsEvent =
nullptr;
63void TRestDetectorElectronDiffusionProcess::LoadConfig(
const string& configFilename,
const string& name) {
70 fRandom =
new TRandom3(fSeed);
72 fGas = GetMetadata<TRestDetectorGas>();
73 if (fGas ==
nullptr) {
74 if (fLongitudinalDiffusionCoefficient == -1 || fTransversalDiffusionCoefficient == -1) {
75 RESTWarning <<
"Gas has not been initialized" <<
RESTendl;
77 <<
"TRestDetectorElectronDiffusionProcess: diffusion parameters are not defined in the rml "
83 RESTWarning <<
"Gas has not been initialized" <<
RESTendl;
85 <<
"TRestDetectorElectronDiffusionProcess: gas work function has not been defined in the "
92 RESTError <<
"A TRestDetectorGas definition was found but REST was not linked to Garfield libraries."
95 <<
"Please, remove the TRestDetectorGas definition, and add gas parameters inside the process "
96 "TRestDetectorElectronDiffusionProcess"
100 if (fGasPressure <= 0) {
101 fGasPressure = fGas->GetPressure();
103 fGas->SetPressure(fGasPressure);
105 if (fElectricField <= 0) {
111 fWValue = fGas->GetWvalue();
115 if (fFanoFactor <= 0) {
119 if (fLongitudinalDiffusionCoefficient <= 0) {
120 fLongitudinalDiffusionCoefficient = fGas->GetLongitudinalDiffusion();
123 if (fTransversalDiffusionCoefficient <= 0) {
124 fTransversalDiffusionCoefficient = fGas->GetTransversalDiffusion();
128 fReadout = GetMetadata<TRestDetectorReadout>();
129 if (fReadout ==
nullptr) {
130 cout <<
"REST ERROR: Readout has not been initialized" << endl;
139 set<int> hitsToProcess;
140 for (
int n = 0; n < static_cast<int>(fInputHitsEvent->GetNumberOfHits()); n++) {
141 if (fInputHitsEvent->GetType(n) == REST_HitType::VETO) {
143 fOutputHitsEvent->
AddHit(fInputHitsEvent->
GetX(n), fInputHitsEvent->
GetY(n),
144 fInputHitsEvent->
GetZ(n), fInputHitsEvent->GetEnergy(n),
145 fInputHitsEvent->GetTime(n), fInputHitsEvent->GetType(n));
147 hitsToProcess.insert(n);
151 if (hitsToProcess.empty()) {
155 double totalEnergy = 0;
156 for (
const auto& hitIndex : hitsToProcess) {
157 totalEnergy += fInputHitsEvent->GetEnergy(hitIndex);
162 Double_t wValue = fWValue;
163 const auto totalElectrons =
static_cast<unsigned int>(totalEnergy * REST_Units::eV / wValue);
166 if (fMaxHits > 0 && totalElectrons > fMaxHits) {
168 wValue = (totalEnergy * REST_Units::eV) / fMaxHits;
171 for (
const auto& hitIndex : hitsToProcess) {
172 TRestHits* hits = fInputHitsEvent->GetHits();
174 const auto energy = hits->GetEnergy(hitIndex);
175 const auto time = hits->GetTime(hitIndex);
176 const auto type = hits->GetType(hitIndex);
182 const Double_t x = hits->GetX(hitIndex);
183 const Double_t y = hits->GetY(hitIndex);
184 const Double_t z = hits->GetZ(hitIndex);
186 for (
int p = 0; p < fReadout->GetNumberOfReadoutPlanes(); p++) {
188 const auto planeType = plane->GetType();
189 if (planeType ==
"veto") {
194 if (fCheckIsInside && !plane->
IsInside({x, y, z})) {
198 Double_t driftDistance = plane->GetDistanceTo({x, y, z});
200 double numberOfElectrons = energy * REST_Units::eV / wValue;
201 if (fUseFanoFactor) {
202 if (fFanoFactor <= 0) {
203 throw runtime_error(
"Fano factor not valid");
205 const auto sigma = TMath::Sqrt(fFanoFactor * numberOfElectrons);
206 numberOfElectrons = fRandom->Gaus(numberOfElectrons, sigma);
207 }
else if (fPoissonElectronExcitation) {
209 numberOfElectrons = fRandom->Poisson(energy * REST_Units::eV / fWValue);
212 if (wValue != fWValue) {
214 numberOfElectrons =
static_cast<unsigned int>(numberOfElectrons * fWValue / wValue);
217 if (numberOfElectrons <= 0) {
218 numberOfElectrons = 1;
221 const Double_t energyPerElectron = energy * REST_Units::eV / numberOfElectrons;
223 Double_t longitudinalDiffusion =
224 10. * TMath::Sqrt(driftDistance / 10.) * fLongitudinalDiffusionCoefficient;
225 Double_t transversalDiffusion =
226 10. * TMath::Sqrt(driftDistance / 10.) * fTransversalDiffusionCoefficient;
228 for (
unsigned int i = 0; i < numberOfElectrons; i++) {
229 if (fAttachment > 0) {
231 isAttached = (fRandom->Uniform(0, 1) > pow(1 - fAttachment, driftDistance / 10.));
240 TVector3 positionAfterDiffusion = {x, y, z};
241 positionAfterDiffusion += {
242 fRandom->Gaus(0, transversalDiffusion),
243 fRandom->Gaus(0, transversalDiffusion),
244 fRandom->Gaus(0, longitudinalDiffusion)
246 if (plane->GetDistanceTo(positionAfterDiffusion) < 0) {
248 positionAfterDiffusion.SetZ(
249 plane->GetPosition().Z() +
250 1E-6 * plane->GetNormal().Z());
252 if (plane->GetDistanceTo(positionAfterDiffusion) > plane->GetHeight()) {
254 positionAfterDiffusion.SetZ(
255 plane->GetPosition().Z() + plane->GetHeight() -
256 1E-6 * plane->GetNormal().Z());
259 if (fCheckIsInside && !plane->IsInside(positionAfterDiffusion)) {
264 const double electronEnergy =
265 fUnitElectronEnergy ? 1 : energyPerElectron * REST_Units::keV / REST_Units::eV;
268 cout <<
"Adding hit. x : " << positionAfterDiffusion.X()
269 <<
" y : " << positionAfterDiffusion.Y() <<
" z : " << positionAfterDiffusion.Z()
270 <<
" en : " << energyPerElectron * REST_Units::keV / REST_Units::eV <<
" keV"
273 fOutputHitsEvent->
AddHit(positionAfterDiffusion.X(), positionAfterDiffusion.Y(),
274 positionAfterDiffusion.Z(), electronEnergy, time, type);
280 cout <<
"TRestDetectorElectronDiffusionProcess. Processed hits total energy : " << totalEnergy
282 cout <<
"TRestDetectorElectronDiffusionProcess. Hits processed : " << hitsToProcess.size() << endl;
283 cout <<
"TRestDetectorElectronDiffusionProcess. Hits added : " << fOutputHitsEvent->GetNumberOfHits()
290 return fOutputHitsEvent;
296 fGasPressure = GetDblParameterWithUnits(
"gasPressure", -1.);
297 fElectricField = GetDblParameterWithUnits(
"electricField", -1.);
298 fWValue = GetDblParameterWithUnits(
"WValue", 0.0) * REST_Units::eV;
299 fFanoFactor = GetDblParameterWithUnits(
"fanoFactor", 0.0);
301 fLongitudinalDiffusionCoefficient =
303 if (fLongitudinalDiffusionCoefficient == -1)
306 RESTWarning <<
"longitudinalDiffusionCoefficient is now OBSOLETE! It will soon disappear."
308 RESTWarning <<
" Please use the shorter form of this parameter : longDiff" <<
RESTendl;
312 if (fTransversalDiffusionCoefficient == -1)
315 RESTWarning <<
"transversalDiffusionCoefficient is now OBSOLETE! It will soon disappear." <<
RESTendl;
316 RESTWarning <<
" Please use the shorter form of this parameter : transDiff" <<
RESTendl;
320 fPoissonElectronExcitation = StringToBool(
GetParameter(
"poissonElectronExcitation",
"true"));
321 fUnitElectronEnergy = StringToBool(
GetParameter(
"unitElectronEnergy",
"false"));
322 fCheckIsInside = StringToBool(
GetParameter(
"checkIsInside",
"false"));
323 fUseFanoFactor = StringToBool(
GetParameter(
"useFano",
"false"));
virtual void SetW(double value)
Sets the electric field of the drift volume. Given in V/mm.
virtual void SetElectricField(double value)
Sets the electric field. Must be given in V/mm.
virtual Double_t GetElectricField() const
Returns the electric field in V/mm.
void InitProcess() override
To be executed at the beginning of the run (outside event loop)
void EndProcess() override
To be executed at the end of the run (outside event loop)
void InitFromConfigFile() override
To make settings from rml file. This method must be implemented in the derived class.
TRestEvent * ProcessEvent(TRestEvent *inputEvent) override
Process one event.
void Initialize() override
Making default settings.
Double_t GetGasFanoFactor() const
Returns the gas fano factor.
Double_t GetX(int n) const
Returns the X-coordinate of hit entry n in mm.
Double_t GetY(int n) const
Returns the Y-coordinate of hit entry n in mm.
Double_t GetZ(int n) const
Returns the Z-coordinate of hit entry n in mm.
void AddHit(Double_t x, Double_t y, Double_t z, Double_t en, Double_t t=0, REST_HitType type=XYZ)
Adds a new hit to this event.
bool IsInside(const TVector3 &point) const
Check if the point is inside any module of the readout plane.
A base class for any REST event.
void SetEventInfo(TRestEvent *eve)
It saves a 3-coordinate position and an energy for each punctual deposition.
@ REST_Extreme
show everything
@ REST_Debug
+show the defined debug messages
Int_t GetChar(std::string hint="Press a KEY to continue ...")
Helps to pause the program, printing a message before pausing.
Double_t StringToDouble(std::string in)
Gets a double from a string.
Int_t StringToInteger(std::string in)
Gets an integer from a string.