gdynamicDigitization
Loading...
Searching...
No Matches
gDosimeterDigitization.cc
Go to the documentation of this file.
1
12#include <fstream>
13
14// See header for API docs.
16 // Time window is the width of one electronics time cell (unit follows the convention
17 // used by the rest of the digitization chain; typically ns).
18 double timeWindow = 10; // electronic readout time-window of the detector
19 double gridStartTime = 0; // defines the windows grid
20 double maxStep = 1 * CLHEP::mm;
21
22 // Readout specs are immutable after initialization and shared by all processed hits.
23 readoutSpecs = std::make_shared<GReadoutSpecs>(timeWindow, gridStartTime, maxStep, log);
24
25 return true;
26}
27
28// See header for API docs.
29std::unique_ptr<GDigitizedData> GDosimeterDigitization::digitizeHitImpl(GHit* ghit, [[maybe_unused]] size_t hitn) {
30
31 auto gdata = std::make_unique<GDigitizedData>(gopts, ghit);
32
33 auto etot = ghit->getTotalEnergyDeposited();
34 auto mass = ghit->getMass();
35 auto dose = etot / mass;
36
37 // Store the detector identity and the total deposited energy.
38 gdata->includeVariable("etot", etot / MeV);
39 gdata->includeVariable("dose", dose / gemc_units::picogray);
40
41 //log->info(0, FUNCTION_NAME, "Edep: ", etot, ", hitn:", ghit->getEdeps().size());
42
43 // // Per-step information used to build the NIEL-weight.
44 // auto pids = ghit->getPids();
45 //
46 // double nielWeight = 0;
47 //
48 // // Accumulate NIEL factor step-by-step. This treats each step independently and sums
49 // // the interpolated factors for supported particle species.
50 // for (size_t stepIndex = 0; stepIndex < pids.size(); stepIndex++) {
51 // // Use absolute PID so negative particle IDs (e.g. -11) are handled.
52 // int pid = std::abs(pids[stepIndex]);
53 //
54 // // Only a few particle types are supported by the calibration data files.
55 // if (pid == 11 || pid == 211 || pid == 2212 || pid == 2112) {
56 // // Convert from total energy to kinetic-like quantity used by the NIEL tables
57 // // by subtracting the particle rest mass (in MeV).
58 // double E = pEnergies[stepIndex] - pMassMeV[pid];
59 // nielWeight += getNielFactorForParticleAtEnergy(pid, E);
60 // }
61 // }
62
63 // gdata->includeVariable("nielWeight", nielWeight);
64
65 return gdata;
66}
67
68// See header for API docs.
69bool GDosimeterDigitization::loadConstantsImpl([[maybe_unused]] int runno,
70 [[maybe_unused]] std::string const& variation) {
71 // Map from particle id to the calibration filename (text, 2 columns).
72 std::map<int, std::string> nielDataFiles;
73 nielDataFiles[11] = "niel_electron.txt";
74 nielDataFiles[211] = "niel_pion.txt";
75 nielDataFiles[2112] = "niel_neutron.txt";
76 nielDataFiles[2212] = "niel_proton.txt";
77
78 // GEMC installation root used to locate plugin data.
79 std::filesystem::path gemcRoot = gutilities::gemc_root();
80
81 for (const auto& [pid, filename] : nielDataFiles) {
82 std::string dataFileWithPath = gemcRoot.string() + "/dosimeterData" + "/Niel/" + filename;
83
84 std::ifstream inputfile(dataFileWithPath);
85 if (!inputfile) {
86 // On Linux, tests may run from the build directory, where plugin data lives under
87 // gdynamicDigitization/...
88 dataFileWithPath = gemcRoot.string() + "/gemc/gdynamicDigitization/dosimeterData" + "/Niel/" + filename;
89 inputfile.open(dataFileWithPath);
90 if (!inputfile) {
91 log->error(EC__FILENOTFOUND, "Error loading dosimeter data for pid <", pid, "> from file ",
92 dataFileWithPath);
93 }
94 }
95
96 log->info(1, " Loading dosimeter data for pid <", pid, "> from file ", dataFileWithPath);
97
98 // Expected file format: repeated pairs (factor, energyMeV).
99 double p0, p1;
100 while (inputfile >> p0 >> p1) {
101 nielfactorMap[pid].push_back(p0);
102 E_nielfactorMap[pid].push_back(p1);
103 }
104 inputfile.close();
105 }
106
107 // Particle rest masses used by the interpolation routine (MeV).
108 pMassMeV[11] = 0.510;
109 pMassMeV[211] = 139.570;
110 pMassMeV[2112] = 939.565;
111 pMassMeV[2212] = 938.272;
112
113 return true;
114}
115
116// See header for API docs.
117double GDosimeterDigitization::getNielFactorForParticleAtEnergy(int pid, double energyMeV) {
118 const auto niel_N = nielfactorMap[pid].size();
119
120 // Guard against missing/empty calibration data.
121 // (If this happens, it indicates loadConstantsImpl did not populate the maps as expected.)
122 if (niel_N == 0) {
123 log->error(EC__FILENOTFOUND, "NIEL tables are empty for pid <", pid, ">. Did loadConstantsImpl fail?");
124 return 0.0;
125 }
126
127 // j is the first index for which energyMeV < E_table[j]. Initialize to "past the end".
128 size_t j = niel_N;
129
130 for (size_t i = 0; i < niel_N; i++) {
131 if (energyMeV < E_nielfactorMap[pid][i]) {
132 j = i;
133 break;
134 }
135 }
136
137 double value = 0.0;
138
139 if (j > 0 && j < niel_N) {
140 // Linear interpolation between (j-1) and j.
141 const auto nielfactor_low = nielfactorMap[pid][j - 1];
142 const auto nielfactor_high = nielfactorMap[pid][j];
143 const auto energy_low = E_nielfactorMap[pid][j - 1];
144 const auto energy_high = E_nielfactorMap[pid][j];
145
146 value = nielfactor_low +
147 ( nielfactor_high - nielfactor_low ) / ( energy_high - energy_low ) * ( energyMeV - energy_low );
148 }
149 else if (j == 0) {
150 // energy below the first threshold: clamp to first value.
151 value = nielfactorMap[pid].front();
152 }
153 else {
154 // energy beyond the last threshold: clamp to last value.
155 value = nielfactorMap[pid].back();
156 }
157
158 log->debug(NORMAL, " pid: ", pid, ", j: ", j, ", value: ", value, ", energy: ", energyMeV);
159
160 return value;
161}
std::shared_ptr< GLogger > log
bool defineReadoutSpecsImpl() override
Defines readout specifications for dosimeter digitization.
std::unique_ptr< GDigitizedData > digitizeHitImpl(GHit *ghit, size_t hitn) override
Digitizes a hit for dosimeter detectors.
bool loadConstantsImpl(int runno, std::string const &variation) override
Loads digitization constants for dosimeter digitization.
std::shared_ptr< GOptions > gopts
Options used by the digitization plugin instance.
std::shared_ptr< const GReadoutSpecs > readoutSpecs
Readout specs are created during initialization and treated as immutable.
double getTotalEnergyDeposited()
double getMass() const
void debug(debug_type type, Args &&... args) const
void info(int level, Args &&... args) const
void error(int exit_code, Args &&... args) const
#define EC__FILENOTFOUND
constexpr G4double picogray
std::filesystem::path gemc_root()