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