REST-for-Physics  v2.3
Rare Event Searches ToolKit for Physics
TRestDetectorElectronDiffusionProcess.cxx
1 
16 #include "TRestDetectorElectronDiffusionProcess.h"
17 
18 using namespace std;
19 
21 
22 TRestDetectorElectronDiffusionProcess::TRestDetectorElectronDiffusionProcess() { Initialize(); }
23 
24 TRestDetectorElectronDiffusionProcess::TRestDetectorElectronDiffusionProcess(const char* configFilename) {
25  Initialize();
26  if (LoadConfigFromFile(configFilename)) {
27  LoadDefaultConfig();
28  }
29 }
30 
31 TRestDetectorElectronDiffusionProcess::~TRestDetectorElectronDiffusionProcess() { delete fOutputHitsEvent; }
32 
33 void 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 
62 void 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 
251  if (GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Extreme) {
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;
269  if (GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Extreme) {
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 }
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.
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.
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.