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();
101 if (fWValue <= 0) fWValue = fGas->GetWvalue();
107 if (fLongitudinalDiffusionCoefficient <= 0) {
111 if (fTransversalDiffusionCoefficient <= 0) {
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})) {
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)
232 positionAfterDiffusion.SetZ(
238 positionAfterDiffusion.SetZ(
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"));