REST-for-Physics  v2.3
Rare Event Searches ToolKit for Physics
TRestDetectorElectronDiffusionProcess.cxx
1
15
16#include "TRestDetectorElectronDiffusionProcess.h"
17
18using namespace std;
19
21
22TRestDetectorElectronDiffusionProcess::TRestDetectorElectronDiffusionProcess() { Initialize(); }
23
24TRestDetectorElectronDiffusionProcess::TRestDetectorElectronDiffusionProcess(const char* configFilename) {
25 Initialize();
26 if (LoadConfigFromFile(configFilename)) {
27 LoadDefaultConfig();
28 }
29}
30
31TRestDetectorElectronDiffusionProcess::~TRestDetectorElectronDiffusionProcess() { delete fOutputHitsEvent; }
32
33void TRestDetectorElectronDiffusionProcess::LoadDefaultConfig() {
34 SetTitle("Default config");
35
36 fElectricField = 2000;
37 fAttachment = 0;
38 fGasPressure = -1;
39}
40
42 SetSectionName(this->ClassName());
43 SetLibraryVersion(LIBRARY_VERSION);
44
45 fElectricField = 0;
46 fAttachment = 0;
47 fGasPressure = -1;
48
49 fTransversalDiffusionCoefficient = 0;
50 fLongitudinalDiffusionCoefficient = 0;
51 fWValue = 0;
52
53 fOutputHitsEvent = new TRestDetectorHitsEvent();
54 fInputHitsEvent = nullptr;
55
56 fGas = nullptr;
57 fReadout = nullptr;
58
59 fRandom = nullptr;
60}
61
62void TRestDetectorElectronDiffusionProcess::LoadConfig(const string& configFilename, const string& name) {
63 if (LoadConfigFromFile(configFilename, name)) {
64 LoadDefaultConfig();
65 }
66}
67
69 fRandom = new TRandom3(fSeed);
70
71 fGas = GetMetadata<TRestDetectorGas>();
72 if (fGas == nullptr) {
73 if (fLongitudinalDiffusionCoefficient == -1 || fTransversalDiffusionCoefficient == -1) {
74 RESTWarning << "Gas has not been initialized" << RESTendl;
75 RESTError
76 << "TRestDetectorElectronDiffusionProcess: diffusion parameters are not defined in the rml "
77 "file!"
78 << RESTendl;
79 exit(-1);
80 }
81 if (fWValue == -1) {
82 RESTWarning << "Gas has not been initialized" << RESTendl;
83 RESTError
84 << "TRestDetectorElectronDiffusionProcess: gas work function has not been defined in the "
85 "rml file!"
86 << RESTendl;
87 exit(-1);
88 }
89 } else {
90#ifndef USE_Garfield
91 RESTError << "A TRestDetectorGas definition was found but REST was not linked to Garfield libraries."
92 << RESTendl;
93 RESTError
94 << "Please, remove the TRestDetectorGas definition, and add gas parameters inside the process "
95 "TRestDetectorElectronDiffusionProcess"
96 << RESTendl;
97 exit(1);
98#endif
99 if (fGasPressure <= 0) fGasPressure = fGas->GetPressure();
100 if (fElectricField <= 0) fElectricField = fGas->GetElectricField();
101 if (fWValue <= 0) fWValue = fGas->GetWvalue();
102
103 fGas->SetPressure(fGasPressure);
104 fGas->SetElectricField(fElectricField);
105 fGas->SetW(fWValue);
106
107 if (fLongitudinalDiffusionCoefficient <= 0) {
108 fLongitudinalDiffusionCoefficient = fGas->GetLongitudinalDiffusion();
109 } // (cm)^1/2
110
111 if (fTransversalDiffusionCoefficient <= 0) {
112 fTransversalDiffusionCoefficient = fGas->GetTransversalDiffusion();
113 } // (cm)^1/2
114 }
115
116 fReadout = GetMetadata<TRestDetectorReadout>();
117 if (fReadout == nullptr) {
118 cout << "REST ERROR: Readout has not been initialized" << endl;
119 exit(-1);
120 }
121}
122
124 fInputHitsEvent = (TRestDetectorHitsEvent*)inputEvent;
125 fOutputHitsEvent->SetEventInfo(fInputHitsEvent);
126
127 set<unsigned int> hitsToProcess; // indices of the hits to process (we do not want to process veto hits)
128 for (unsigned int n = 0; n < fInputHitsEvent->GetNumberOfHits(); n++) {
129 if (fInputHitsEvent->GetType(n) == REST_HitType::VETO) {
130 // keep unprocessed hits as they are
131 fOutputHitsEvent->AddHit(fInputHitsEvent->GetX(n), fInputHitsEvent->GetY(n),
132 fInputHitsEvent->GetZ(n), fInputHitsEvent->GetEnergy(n),
133 fInputHitsEvent->GetTime(n), fInputHitsEvent->GetType(n));
134 } else {
135 hitsToProcess.insert(n);
136 }
137 }
138
139 if (hitsToProcess.empty()) {
140 return nullptr;
141 }
142
143 double totalEnergy = 0;
144 for (const auto& hitIndex : hitsToProcess) {
145 totalEnergy += fInputHitsEvent->GetEnergy(hitIndex);
146 }
147
148 bool isAttached;
149
150 Double_t wValue = fWValue;
151 const unsigned int totalElectrons = totalEnergy * REST_Units::eV / wValue;
152
153 // TODO: double check this
154 if (fMaxHits > 0 && totalElectrons > fMaxHits) {
155 // set a fake w-value if max hits are limited. this fake w-value will be larger
156 wValue = (totalEnergy * REST_Units::eV) / fMaxHits;
157 }
158
159 for (const auto& hitIndex : hitsToProcess) {
160 TRestHits* hits = fInputHitsEvent->GetHits();
161
162 const auto energy = hits->GetEnergy(hitIndex);
163 const auto time = hits->GetTime(hitIndex);
164 const auto type = hits->GetType(hitIndex);
165
166 if (energy <= 0) {
167 continue;
168 }
169
170 const Double_t x = hits->GetX(hitIndex);
171 const Double_t y = hits->GetY(hitIndex);
172 const Double_t z = hits->GetZ(hitIndex);
173
174 for (int p = 0; p < fReadout->GetNumberOfReadoutPlanes(); p++) {
175 TRestDetectorReadoutPlane* plane = &(*fReadout)[p];
176 const auto planeType = plane->GetType();
177 if (planeType == "veto") {
178 // do not drift veto planes
179 continue;
180 }
181
182 if (fCheckIsInside && !plane->IsInside({x, y, z})) {
183 continue;
184 }
185
186 Double_t driftDistance = plane->GetDistanceTo({x, y, z});
187
188 Int_t numberOfElectrons;
189 if (fPoissonElectronExcitation) {
190 numberOfElectrons = fRandom->Poisson(energy * REST_Units::eV / fWValue);
191 if (wValue != fWValue) {
192 // reduce the number of electrons to improve speed
193 numberOfElectrons = numberOfElectrons * fWValue / wValue;
194 }
195 } else {
196 numberOfElectrons = energy * REST_Units::eV / wValue;
197 }
198
199 if (numberOfElectrons <= 0) {
200 numberOfElectrons = 1;
201 }
202
203 const Double_t energyPerElectron = energy * REST_Units::eV / numberOfElectrons;
204
205 while (numberOfElectrons > 0) {
206 numberOfElectrons--;
207
208 Double_t longitudinalDiffusion =
209 10. * TMath::Sqrt(driftDistance / 10.) * fLongitudinalDiffusionCoefficient; // mm
210 Double_t transversalDiffusion =
211 10. * TMath::Sqrt(driftDistance / 10.) * fTransversalDiffusionCoefficient; // mm
212
213 if (fAttachment > 0) {
214 // TODO: where is this formula from?
215 isAttached = (fRandom->Uniform(0, 1) > pow(1 - fAttachment, driftDistance / 10.));
216 } else {
217 isAttached = false;
218 }
219
220 if (isAttached) {
221 continue;
222 }
223
224 TVector3 positionAfterDiffusion = {x, y, z};
225 positionAfterDiffusion += {
226 fRandom->Gaus(0, transversalDiffusion), //
227 fRandom->Gaus(0, transversalDiffusion), //
228 fRandom->Gaus(0, longitudinalDiffusion) //
229 };
230 if (plane->GetDistanceTo(positionAfterDiffusion) < 0) {
231 // electron has been moved under the plane
232 positionAfterDiffusion.SetZ(
233 plane->GetPosition().Z() +
234 1E-6 * plane->GetNormal().Z()); // add a delta to make sure readout finds it
235 }
236 if (plane->GetDistanceTo(positionAfterDiffusion) > plane->GetHeight()) {
237 // electron has been moved over the plane
238 positionAfterDiffusion.SetZ(
239 plane->GetPosition().Z() + plane->GetHeight() -
240 1E-6 * plane->GetNormal().Z()); // add a delta to make sure readout finds it
241 }
242
243 if (!fCheckIsInside && !plane->IsInside(positionAfterDiffusion)) {
244 // electron has been moved outside the readout plane
245 continue;
246 }
247
248 const double electronEnergy =
249 fUnitElectronEnergy ? 1 : energyPerElectron * REST_Units::keV / REST_Units::eV;
250
252 cout << "Adding hit. x : " << positionAfterDiffusion.X()
253 << " y : " << positionAfterDiffusion.Y() << " z : " << positionAfterDiffusion.Z()
254 << " en : " << energyPerElectron * REST_Units::keV / REST_Units::eV << " keV"
255 << endl;
256 }
257 fOutputHitsEvent->AddHit(positionAfterDiffusion.X(), positionAfterDiffusion.Y(),
258 positionAfterDiffusion.Z(), electronEnergy, time, type);
259 }
260 }
261 }
262
263 if (this->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) {
264 cout << "TRestDetectorElectronDiffusionProcess. Processed hits total energy : " << totalEnergy
265 << endl;
266 cout << "TRestDetectorElectronDiffusionProcess. Hits processed : " << hitsToProcess.size() << endl;
267 cout << "TRestDetectorElectronDiffusionProcess. Hits added : " << fOutputHitsEvent->GetNumberOfHits()
268 << endl;
270 GetChar();
271 }
272 }
273
274 return fOutputHitsEvent;
275}
276
278
280 fGasPressure = GetDblParameterWithUnits("gasPressure", -1.);
281 fElectricField = GetDblParameterWithUnits("electricField", -1.);
282 fWValue = GetDblParameterWithUnits("WValue", 0.0) * REST_Units::eV;
283 fAttachment = StringToDouble(GetParameter("attachment", "0"));
284 fLongitudinalDiffusionCoefficient =
285 StringToDouble(GetParameter("longitudinalDiffusionCoefficient", "-1"));
286 if (fLongitudinalDiffusionCoefficient == -1)
287 fLongitudinalDiffusionCoefficient = StringToDouble(GetParameter("longDiff", "-1"));
288 else {
289 RESTWarning << "longitudinalDiffusionCoefficient is now OBSOLETE! It will soon dissapear."
290 << RESTendl;
291 RESTWarning << " Please use the shorter form of this parameter : longDiff" << RESTendl;
292 }
293
294 fTransversalDiffusionCoefficient = StringToDouble(GetParameter("transversalDiffusionCoefficient", "-1"));
295 if (fTransversalDiffusionCoefficient == -1)
296 fTransversalDiffusionCoefficient = StringToDouble(GetParameter("transDiff", "-1"));
297 else {
298 RESTWarning << "transversalDiffusionCoefficient is now OBSOLETE! It will soon dissapear." << RESTendl;
299 RESTWarning << " Please use the shorter form of this parameter : transDiff" << RESTendl;
300 }
301 fMaxHits = StringToInteger(GetParameter("maxHits", "1000"));
302 fSeed = StringToDouble(GetParameter("seed", "0"));
303 fPoissonElectronExcitation = StringToBool(GetParameter("poissonElectronExcitation", "false"));
304 fUnitElectronEnergy = StringToBool(GetParameter("unitElectronEnergy", "false"));
305 fCheckIsInside = StringToBool(GetParameter("checkIsInside", "true"));
306}
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 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.
Definition: TRestEvent.h:38
void SetEventInfo(TRestEvent *eve)
Definition: TRestEvent.cxx:137
It saves a 3-coordinate position and an energy for each punctual deposition.
Definition: TRestHits.h:39
endl_t RESTendl
Termination flag object for TRestStringOutput.
Int_t LoadConfigFromFile(const std::string &configFilename, const std::string &sectionName="")
Give the file name, find out the corresponding section. Then call the main starter.
void SetLibraryVersion(TString version)
Set the library version of this metadata class.
TRestStringOutput::REST_Verbose_Level GetVerboseLevel()
returns the verboselevel in type of REST_Verbose_Level enumerator
void SetSectionName(std::string sName)
set the section name, clear the section content
std::string GetParameter(std::string parName, TiXmlElement *e, TString defaultValue=PARAMETER_NOT_FOUND_STR)
Returns the value for the parameter named parName in the given section.
@ 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.