16 #include "TRestDetectorElectronDiffusionProcess.h"
22 TRestDetectorElectronDiffusionProcess::TRestDetectorElectronDiffusionProcess() { Initialize(); }
24 TRestDetectorElectronDiffusionProcess::TRestDetectorElectronDiffusionProcess(
const char* configFilename) {
26 if (LoadConfigFromFile(configFilename)) {
31 TRestDetectorElectronDiffusionProcess::~TRestDetectorElectronDiffusionProcess() {
delete fOutputHitsEvent; }
33 void TRestDetectorElectronDiffusionProcess::LoadDefaultConfig() {
34 SetTitle(
"Default config");
36 fElectricField = 2000;
42 SetSectionName(this->ClassName());
43 SetLibraryVersion(LIBRARY_VERSION);
49 fTransversalDiffusionCoefficient = 0;
50 fLongitudinalDiffusionCoefficient = 0;
54 fInputHitsEvent =
nullptr;
62 void TRestDetectorElectronDiffusionProcess::LoadConfig(
const string& configFilename,
const string& name) {
63 if (LoadConfigFromFile(configFilename, name)) {
69 fRandom =
new TRandom3(fSeed);
71 fGas = GetMetadata<TRestDetectorGas>();
72 if (fGas ==
nullptr) {
73 if (fLongitudinalDiffusionCoefficient == -1 || fTransversalDiffusionCoefficient == -1) {
74 RESTWarning <<
"Gas has not been initialized" << RESTendl;
76 <<
"TRestDetectorElectronDiffusionProcess: diffusion parameters are not defined in the rml "
82 RESTWarning <<
"Gas has not been initialized" << RESTendl;
84 <<
"TRestDetectorElectronDiffusionProcess: gas work function has not been defined in the "
91 RESTError <<
"A TRestDetectorGas definition was found but REST was not linked to Garfield libraries."
94 <<
"Please, remove the TRestDetectorGas definition, and add gas parameters inside the process "
95 "TRestDetectorElectronDiffusionProcess"
99 if (fGasPressure <= 0) fGasPressure = fGas->GetPressure();
100 if (fElectricField <= 0) fElectricField = fGas->GetElectricField();
101 if (fWValue <= 0) fWValue = fGas->GetWvalue();
103 fGas->SetPressure(fGasPressure);
104 fGas->SetElectricField(fElectricField);
107 if (fLongitudinalDiffusionCoefficient <= 0) {
108 fLongitudinalDiffusionCoefficient = fGas->GetLongitudinalDiffusion();
111 if (fTransversalDiffusionCoefficient <= 0) {
112 fTransversalDiffusionCoefficient = fGas->GetTransversalDiffusion();
116 fReadout = GetMetadata<TRestDetectorReadout>();
117 if (fReadout ==
nullptr) {
118 cout <<
"REST ERROR: Readout has not been initialized" << endl;
127 set<unsigned int> hitsToProcess;
128 for (
unsigned int n = 0; n < fInputHitsEvent->GetNumberOfHits(); n++) {
129 if (fInputHitsEvent->GetType(n) == REST_HitType::VETO) {
131 fOutputHitsEvent->AddHit(fInputHitsEvent->GetX(n), fInputHitsEvent->GetY(n),
132 fInputHitsEvent->GetZ(n), fInputHitsEvent->GetEnergy(n),
133 fInputHitsEvent->GetTime(n), fInputHitsEvent->GetType(n));
135 hitsToProcess.insert(n);
139 if (hitsToProcess.empty()) {
143 double totalEnergy = 0;
144 for (
const auto& hitIndex : hitsToProcess) {
145 totalEnergy += fInputHitsEvent->GetEnergy(hitIndex);
150 Double_t wValue = fWValue;
151 const unsigned int totalElectrons = totalEnergy * REST_Units::eV / wValue;
154 if (fMaxHits > 0 && totalElectrons > fMaxHits) {
156 wValue = (totalEnergy * REST_Units::eV) / fMaxHits;
159 for (
const auto& hitIndex : hitsToProcess) {
160 TRestHits* hits = fInputHitsEvent->GetHits();
162 const auto energy = hits->GetEnergy(hitIndex);
163 const auto time = hits->GetTime(hitIndex);
164 const auto type = hits->GetType(hitIndex);
170 const Double_t x = hits->GetX(hitIndex);
171 const Double_t y = hits->GetY(hitIndex);
172 const Double_t z = hits->GetZ(hitIndex);
174 for (
int p = 0; p < fReadout->GetNumberOfReadoutPlanes(); p++) {
176 const auto planeType = plane->GetType();
177 if (planeType ==
"veto") {
182 if (fCheckIsInside && !plane->
IsInside({x, y, z})) {
186 Double_t driftDistance = plane->GetDistanceTo({x, y, z});
188 Int_t numberOfElectrons;
189 if (fPoissonElectronExcitation) {
190 numberOfElectrons = fRandom->Poisson(energy * REST_Units::eV / fWValue);
191 if (wValue != fWValue) {
193 numberOfElectrons = numberOfElectrons * fWValue / wValue;
196 numberOfElectrons = energy * REST_Units::eV / wValue;
199 if (numberOfElectrons <= 0) {
200 numberOfElectrons = 1;
203 const Double_t energyPerElectron = energy * REST_Units::eV / numberOfElectrons;
205 while (numberOfElectrons > 0) {
208 Double_t longitudinalDiffusion =
209 10. * TMath::Sqrt(driftDistance / 10.) * fLongitudinalDiffusionCoefficient;
210 Double_t transversalDiffusion =
211 10. * TMath::Sqrt(driftDistance / 10.) * fTransversalDiffusionCoefficient;
213 if (fAttachment > 0) {
215 isAttached = (fRandom->Uniform(0, 1) > pow(1 - fAttachment, driftDistance / 10.));
224 TVector3 positionAfterDiffusion = {x, y, z};
225 positionAfterDiffusion += {
226 fRandom->Gaus(0, transversalDiffusion),
227 fRandom->Gaus(0, transversalDiffusion),
228 fRandom->Gaus(0, longitudinalDiffusion)
230 if (plane->GetDistanceTo(positionAfterDiffusion) < 0) {
232 positionAfterDiffusion.SetZ(
233 plane->GetPosition().Z() +
234 1E-6 * plane->GetNormal().Z());
236 if (plane->GetDistanceTo(positionAfterDiffusion) > plane->GetHeight()) {
238 positionAfterDiffusion.SetZ(
239 plane->GetPosition().Z() + plane->GetHeight() -
240 1E-6 * plane->GetNormal().Z());
243 if (!fCheckIsInside && !plane->IsInside(positionAfterDiffusion)) {
248 const double electronEnergy =
249 fUnitElectronEnergy ? 1 : energyPerElectron * REST_Units::keV / REST_Units::eV;
252 cout <<
"Adding hit. x : " << positionAfterDiffusion.X()
253 <<
" y : " << positionAfterDiffusion.Y() <<
" z : " << positionAfterDiffusion.Z()
254 <<
" en : " << energyPerElectron * REST_Units::keV / REST_Units::eV <<
" keV"
257 fOutputHitsEvent->AddHit(positionAfterDiffusion.X(), positionAfterDiffusion.Y(),
258 positionAfterDiffusion.Z(), electronEnergy, time, type);
264 cout <<
"TRestDetectorElectronDiffusionProcess. Processed hits total energy : " << totalEnergy
266 cout <<
"TRestDetectorElectronDiffusionProcess. Hits processed : " << hitsToProcess.size() << endl;
267 cout <<
"TRestDetectorElectronDiffusionProcess. Hits added : " << fOutputHitsEvent->GetNumberOfHits()
274 return fOutputHitsEvent;
280 fGasPressure = GetDblParameterWithUnits(
"gasPressure", -1.);
281 fElectricField = GetDblParameterWithUnits(
"electricField", -1.);
282 fWValue = GetDblParameterWithUnits(
"WValue", 0.0) * REST_Units::eV;
284 fLongitudinalDiffusionCoefficient =
286 if (fLongitudinalDiffusionCoefficient == -1)
289 RESTWarning <<
"longitudinalDiffusionCoefficient is now OBSOLETE! It will soon dissapear."
291 RESTWarning <<
" Please use the shorter form of this parameter : longDiff" <<
RESTendl;
295 if (fTransversalDiffusionCoefficient == -1)
298 RESTWarning <<
"transversalDiffusionCoefficient is now OBSOLETE! It will soon dissapear." <<
RESTendl;
299 RESTWarning <<
" Please use the shorter form of this parameter : transDiff" <<
RESTendl;
303 fPoissonElectronExcitation = StringToBool(
GetParameter(
"poissonElectronExcitation",
"false"));
304 fUnitElectronEnergy = StringToBool(
GetParameter(
"unitElectronEnergy",
"false"));
305 fCheckIsInside = StringToBool(
GetParameter(
"checkIsInside",
"true"));
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.
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.