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