File indexing completed on 2025-12-16 09:29:10
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 "SteppingAction.hh"
0030
0031 #include "ChromosomeMapper.hh"
0032 #include "DNAGeometry.hh"
0033 #include "DNAHit.hh"
0034 #include "DetectorConstruction.hh"
0035 #include "EventAction.hh"
0036 #include "OctreeNode.hh"
0037 #include "PlacementVolumeInfo.hh"
0038 #include "UtilityFunctions.hh"
0039
0040 #include "G4AffineTransform.hh"
0041 #include "G4LogicalVolume.hh"
0042 #include "G4RunManager.hh"
0043 #include "G4StepPoint.hh"
0044 #include "G4ThreeVector.hh"
0045 #include "G4VPhysicalVolume.hh"
0046 #include "G4VTouchable.hh"
0047 #include "Randomize.hh"
0048
0049
0050
0051 SteppingAction::SteppingAction(EventAction* evt) : fEventAction(evt)
0052 {
0053 const auto* det = dynamic_cast<const DetectorConstruction*>(
0054 G4RunManager::GetRunManager()->GetUserDetectorConstruction());
0055
0056 fDNAGeometry = det->GetDNAGeometry();
0057 }
0058
0059
0060
0061 void SteppingAction::UserSteppingAction(const G4Step* aStep)
0062 {
0063 G4double edep = aStep->GetTotalEnergyDeposit();
0064 if (edep == 0) {
0065 return;
0066 }
0067
0068
0069 const G4VTouchable* touch = aStep->GetPreStepPoint()->GetTouchable();
0070
0071
0072 G4LogicalVolume* dnaVol = fDNAGeometry->GetDNAChemVolumePointer();
0073 G4int depth = touch->GetHistoryDepth();
0074 G4bool isInDNARegion = false;
0075
0076 if (depth >= 0) {
0077 fEventAction->AddCellEdep(edep);
0078 }
0079
0080 while ((depth >= 0) && !isInDNARegion) {
0081 if (touch->GetVolume(depth) != nullptr) {
0082 isInDNARegion = isInDNARegion || (touch->GetVolume(depth)->GetLogicalVolume() == dnaVol);
0083 }
0084 else {
0085 G4cout << "Null pointer volume in mother with depth of " << touch->GetHistoryDepth()
0086 << " looking for volume at depth " << depth << G4endl;
0087 assert(depth < 0);
0088 }
0089 depth--;
0090 }
0091
0092 if (isInDNARegion) {
0093 ProcessDNARegionHit(aStep);
0094 }
0095
0096 G4ThreeVector prepos = aStep->GetPreStepPoint()->GetPosition();
0097 if (fDNAGeometry->GetChromosomeMapper()->GetChromosome(prepos) != nullptr) {
0098 DoChromosomeRegionHit(prepos, edep, false);
0099 }
0100
0101 if (aStep->GetTrack()->GetTrackID() == 1) {
0102 fEventAction->SetPrimStopPos(prepos);
0103 G4double tl = aStep->GetStepLength();
0104 fEventAction->AddTrackLengthCell(tl);
0105 if (fDNAGeometry->GetChromosomeMapper()->GetChromosome(prepos) != nullptr) {
0106 fEventAction->AddTrackLengthChro(tl);
0107 }
0108 }
0109 }
0110
0111
0112
0113 void SteppingAction::ProcessDNARegionHit(const G4Step* aStep)
0114 {
0115 G4double edep = aStep->GetTotalEnergyDeposit();
0116 const G4VTouchable* touch = aStep->GetPreStepPoint()->GetTouchable();
0117 G4ThreeVector pos =
0118 aStep->GetPreStepPoint()->GetPosition()
0119 + G4UniformRand()
0120 * (aStep->GetPostStepPoint()->GetPosition() - aStep->GetPreStepPoint()->GetPosition());
0121 G4VPhysicalVolume* pv = aStep->GetPreStepPoint()->GetPhysicalVolume();
0122 G4LogicalVolume* lv = pv->GetLogicalVolume();
0123
0124 std::vector<G4VPhysicalVolume*> molvec;
0125 OctreeNode* parentNode;
0126 G4AffineTransform transform = touch->GetHistory()->GetTopTransform();
0127 parentNode = fDNAGeometry->GetTopOctreeNode(lv);
0128 if (parentNode == nullptr) {
0129 parentNode = fDNAGeometry->GetTopOctreeNode(pv->GetMotherLogical());
0130 if (parentNode != nullptr) {
0131
0132
0133
0134 pv = touch->GetVolume(1);
0135 transform = touch->GetHistory()->GetTransform(touch->GetHistoryDepth() - 1);
0136 }
0137 }
0138
0139 G4ThreeVector localPos = transform.TransformPoint(pos);
0140
0141 if (parentNode != nullptr) {
0142 molvec = parentNode->SearchOctree(localPos, fDNAGeometry->GetDirectInteractionRange());
0143 }
0144
0145
0146 if (fDNAGeometry->GetVerbosity() > 1) {
0147 if (parentNode != nullptr) {
0148 G4String lvname = pv->GetLogicalVolume()->GetName();
0149 G4cout << "Found octree for logical volume: " << lvname << G4endl;
0150 }
0151 else {
0152
0153
0154
0155 if (pv->GetLogicalVolume() != fDNAGeometry->GetDNAChemVolumePointer()) {
0156 G4String lvname = pv->GetLogicalVolume()->GetName();
0157 G4String motherlvname;
0158 if (lv != nullptr) {
0159 motherlvname = lv->GetName();
0160 }
0161 G4cout << "Could not find octree for logical volume." << G4endl
0162 << "Particle in LV: " << lvname << ", with mother LV: " << motherlvname << G4endl;
0163 }
0164 }
0165 }
0166
0167 if (!molvec.empty()) {
0168
0169 G4VPhysicalVolume* closest = molvec[0];
0170 G4double dist = (closest->GetTranslation() - localPos).mag();
0171 if (molvec.size() > 1) {
0172 G4double newdist;
0173 for (auto it = molvec.begin() + 1; it != molvec.end(); it++) {
0174 newdist = ((*it)->GetTranslation() - localPos).mag();
0175 if (newdist < dist) {
0176 dist = newdist;
0177 closest = (*it);
0178 }
0179 }
0180 }
0181 G4bool isDNAHit = (dist < fDNAGeometry->GetDirectInteractionRange());
0182 if (isDNAHit) {
0183 DoChromosomeDNAHit(pos, localPos, edep, dist, closest->GetName(), pv->GetName());
0184 DoChromosomeRegionHit(pos, edep, true);
0185 }
0186 }
0187 }
0188
0189
0190
0191 void SteppingAction::DoChromosomeRegionHit(const G4ThreeVector& pos, const G4double& edep,
0192 const G4bool& dnahit)
0193 {
0194
0195
0196 G4String chromosome = fDNAGeometry->GetChromosomeMapper()->GetCurrentChromosomeKey(pos);
0197 if (!(chromosome.empty())) {
0198 fEventAction->AddChromosomeEdep(chromosome, edep, dnahit);
0199 }
0200 }
0201
0202
0203
0204 void SteppingAction::DoChromosomeDNAHit(const G4ThreeVector& pos, const G4ThreeVector& localPos,
0205 const G4double& edep, const G4double& dist,
0206 const G4String& pvName, const G4String& motherName)
0207 {
0208 G4int placementIdx = std::stoi(utility::Split(motherName, '-').at(1));
0209 std::vector<G4String> pvNameVec = utility::Split(pvName, '-');
0210 molecule mol = utility::GetMoleculeEnum(pvNameVec.at(0));
0211 G4int chainIdx = std::stoi(pvNameVec.at(1));
0212 G4int strandIdx = std::stoi(pvNameVec.at(2));
0213 int64_t baseIdx = std::stoll(pvNameVec.at(3));
0214
0215
0216 chainIdx = fDNAGeometry->GetGlobalChain(placementIdx, chainIdx);
0217 baseIdx += fDNAGeometry->GetStartIdx(placementIdx, chainIdx);
0218
0219 if (fDNAGeometry->GetStrandsFlipped(placementIdx)) {
0220 strandIdx = (strandIdx + 1) % 2;
0221 }
0222 G4String chromosome = fDNAGeometry->GetChromosomeMapper()->GetCurrentChromosomeKey(pos);
0223 const DNAHit* dnaHit = new DNAHit(mol, placementIdx, chainIdx, strandIdx, baseIdx, pos, localPos,
0224 edep, dist, chromosome);
0225
0226 fEventAction->AddDNAHit(dnaHit);
0227 }
0228
0229