File indexing completed on 2026-03-30 07:50:59
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029 #include "LETAccumulable.hh"
0030
0031 #include "G4EmCalculator.hh"
0032 #include "G4LogicalVolume.hh"
0033 #include "G4ParticleDefinition.hh"
0034
0035 #include "Hit.hh"
0036 #include "Manager.hh"
0037 #include "VoxelizedSensitiveDetector.hh"
0038 #include <G4SystemOfUnits.hh>
0039
0040 #include <tuple>
0041
0042 namespace RadioBio
0043 {
0044
0045
0046
0047 LETAccumulable::LETAccumulable() : VRadiobiologicalAccumulable("LET") {}
0048
0049
0050
0051 void LETAccumulable::Merge(const G4VAccumulable& rhs)
0052 {
0053 if (GetVerboseLevel() > 0) {
0054 G4cout << "LETAccumulable::Merge()" << G4endl;
0055 }
0056 const LETAccumulable& other = dynamic_cast<const LETAccumulable&>(rhs);
0057
0058
0059 fTotalLETT += other.GetTotalLETT();
0060 fDTotalLETT += other.GetDTotalLETT();
0061 fDTotalLETD += other.GetDTotalLETD();
0062 fTotalLETD += other.GetTotalLETD();
0063
0064
0065 auto rhsIonLetStore = other.GetIonLetStore();
0066
0067
0068 for (unsigned int l = 0; l < rhsIonLetStore.size(); l++) {
0069 G4int PDGencoding = rhsIonLetStore[l].GetPDGencoding();
0070 size_t q;
0071
0072 for (q = 0; q < fIonLetStore.size(); q++) {
0073
0074 if (fIonLetStore[q].GetPDGencoding() == PDGencoding) {
0075 if (rhsIonLetStore[l].IsPrimary() == fIonLetStore[q].IsPrimary()) break;
0076 }
0077 }
0078
0079 if (q == fIonLetStore.size())
0080 fIonLetStore.push_back(rhsIonLetStore[l]);
0081 else
0082 fIonLetStore[q].Merge(&(rhsIonLetStore[l]));
0083 }
0084 }
0085
0086
0087
0088 void LETAccumulable::Reset()
0089 {
0090 if (GetVerboseLevel() > 0) {
0091 G4cout << "LETAccumulable::Reset()" << G4endl;
0092 }
0093 if (fInitialized) {
0094 fTotalLETT = 0.0;
0095 fDTotalLETT = 0.0;
0096 fDTotalLETD = 0.0;
0097 fTotalLETD = 0.0;
0098 fIonLetStore.clear();
0099 }
0100 else {
0101 Initialize();
0102 }
0103 }
0104
0105
0106
0107
0108 void LETAccumulable::Accumulate(Hit* hit)
0109 {
0110 if (GetVerboseLevel() > 1) {
0111 G4cout << "LETAccumulable::Accumulate()" << G4endl;
0112 }
0113
0114
0115 if (hit->GetDeltaE() == 0. || hit->GetTrackLength() == 0.) return;
0116
0117
0118 G4int Z = hit->GetPartType()->GetAtomicNumber();
0119 if (Z < 1) return;
0120
0121 G4int PDGencoding = hit->GetPartType()->GetPDGEncoding();
0122
0123 if (PDGencoding == 22 || PDGencoding == 11) return;
0124
0125
0126 PDGencoding -= PDGencoding % 10;
0127
0128
0129 G4int xIndex = hit->GetXindex();
0130 G4int yIndex = hit->GetYindex();
0131 ;
0132 G4int zIndex = hit->GetZindex();
0133 ;
0134
0135 G4int voxel =
0136 VoxelizedSensitiveDetector::GetInstance()->GetThisVoxelNumber(xIndex, yIndex, zIndex);
0137
0138
0139 G4double ekinMean = hit->GetEkinMean();
0140
0141
0142 const G4ParticleDefinition* particleDef = hit->GetPartType();
0143
0144
0145 G4Material* mat = hit->GetPhysicalVolume()->GetLogicalVolume()->GetMaterial();
0146
0147
0148 G4EmCalculator emCal;
0149
0150 G4double Lsn = emCal.ComputeElectronicDEDX(ekinMean, particleDef, mat);
0151
0152
0153
0154
0155 G4double DE = hit->GetDeltaE();
0156
0157
0158 G4double DEElectrons = hit->GetElectronEnergy();
0159
0160
0161 G4double DX = hit->GetTrackLength();
0162
0163
0164 G4int trackID = hit->GetTrackID();
0165
0166
0167
0168 fTotalLETD[voxel] += (DE + DEElectrons) * Lsn;
0169
0170 fDTotalLETD[voxel] += DE + DEElectrons;
0171
0172 fTotalLETT[voxel] += DX * Lsn;
0173
0174 fDTotalLETT[voxel] += DX;
0175
0176 size_t l;
0177 for (l = 0; l < fIonLetStore.size(); l++) {
0178
0179 if (fIonLetStore[l].GetPDGencoding() == PDGencoding)
0180 if (((trackID == 1) && (fIonLetStore[l].IsPrimary()))
0181 || ((trackID != 1) && (!fIonLetStore[l].IsPrimary())))
0182 break;
0183 }
0184
0185
0186 if (l == fIonLetStore.size()) {
0187
0188 G4int A = particleDef->GetAtomicMass();
0189
0190
0191 G4String fullName = particleDef->GetParticleName();
0192 G4String name = fullName.substr(0, fullName.find("["));
0193
0194 IonLet ion(trackID, PDGencoding, fullName, name, Z, A,
0195 VoxelizedSensitiveDetector::GetInstance()->GetTotalVoxelNumber());
0196 fIonLetStore.push_back(ion);
0197 }
0198
0199
0200 fIonLetStore[l].Update(voxel, DE, DEElectrons, Lsn, DX);
0201 }
0202
0203
0204
0205 G4int LETAccumulable::GetVerboseLevel() const
0206 {
0207
0208 return Manager::GetInstance()->GetQuantity("LET")->GetVerboseLevel();
0209 }
0210
0211
0212
0213 void LETAccumulable::Initialize()
0214 {
0215 if (GetVerboseLevel() > 0) {
0216 G4cout << "LETAccumulable::Initialize(): " << G4endl;
0217 }
0218
0219 G4int voxNumber = VoxelizedSensitiveDetector::GetInstance()->GetTotalVoxelNumber();
0220
0221 fTotalLETT = array_type(0.0, voxNumber);
0222 fTotalLETD = array_type(0.0, voxNumber);
0223 fDTotalLETT = array_type(0.0, voxNumber);
0224 fDTotalLETD = array_type(0.0, voxNumber);
0225 fInitialized = true;
0226 }
0227
0228
0229
0230 }