Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-03-31 07:50:27

0001 //
0002 // ********************************************************************
0003 // * License and Disclaimer                                           *
0004 // *                                                                  *
0005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
0006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
0007 // * conditions of the Geant4 Software License,  included in the file *
0008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
0009 // * include a list of copyright holders.                             *
0010 // *                                                                  *
0011 // * Neither the authors of this software system, nor their employing *
0012 // * institutes,nor the agencies providing financial support for this *
0013 // * work  make  any representation or  warranty, express or implied, *
0014 // * regarding  this  software system or assume any liability for its *
0015 // * use.  Please see the license in the file  LICENSE  and URL above *
0016 // * for the full disclaimer and the limitation of liability.         *
0017 // *                                                                  *
0018 // * This  code  implementation is the result of  the  scientific and *
0019 // * technical work of the GEANT4 collaboration.                      *
0020 // * By using,  copying,  modifying or  distributing the software (or *
0021 // * any work based  on the software)  you  agree  to acknowledge its *
0022 // * use  in  resulting  scientific  publications,  and indicate your *
0023 // * acceptance of all terms of the Geant4 Software license.          *
0024 // ********************************************************************
0025 //
0026 /// \file DNAParser.cc
0027 /// \brief Implementation of the DNAParser class
0028 
0029 // Authors: S. Meylan and C. Villagrasa (IRSN, France)
0030 // Updated: H. Tran (IRSN), France: 20/12/2018
0031 //
0032 
0033 #include "DNAParser.hh"
0034 
0035 #include "G4Box.hh"
0036 #include "G4DNAChemistryManager.hh"
0037 #include "G4LogicalVolume.hh"
0038 #include "G4Material.hh"
0039 #include "G4NistManager.hh"
0040 #include "G4Orb.hh"
0041 #include "G4PVPlacement.hh"
0042 #include "G4SubtractionSolid.hh"
0043 #include "G4SystemOfUnits.hh"
0044 #include "G4VPhysicalVolume.hh"
0045 #include "G4VSolid.hh"
0046 
0047 #include <fstream>
0048 
0049 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0050 // Molecule struct def
0051 struct DNAParser::Molecule
0052 {
0053     Molecule(std::string name, int copyNumber, const G4ThreeVector& position, double radius,
0054              double waterRadius, const std::string& material, int strand)
0055       : fName(name),
0056         fMaterial(material),
0057         fCopyNumber(copyNumber),
0058         fPosition(position),
0059         fRadius(radius),
0060         fRadiusWater(waterRadius),
0061         fStrand(strand)
0062     {}
0063 
0064     G4String fName;
0065     G4String fMaterial;
0066     G4int fCopyNumber;
0067     G4ThreeVector fPosition;
0068     G4double fRadius;
0069     G4double fRadiusWater;
0070     G4int fStrand;
0071 
0072     G4bool operator<(const Molecule& rhs) const { return (fPosition.z() < rhs.fPosition.z()); }
0073 };
0074 
0075 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0076 DNAParser::DNAParser() : fSize(0), fGeoName(""), fpWater(nullptr), fpGun(new G4MoleculeGun())
0077 {
0078   EnumParser();
0079 }
0080 
0081 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0082 
0083 DNAParser::~DNAParser() = default;
0084 
0085 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0086 
0087 G4LogicalVolume* DNAParser::CreateLogicVolume()
0088 {
0089   G4NistManager* pMan = G4NistManager::Instance();
0090   fpWater = pMan->FindOrBuildMaterial("G4_WATER");
0091 
0092   G4String boxNameSolid = fGeoName + "_solid";
0093 
0094   G4Box* pBoxSolid = new G4Box(boxNameSolid, fSize / 2, fSize / 2, fSize / 2);
0095 
0096   G4String boxNameLogic = fGeoName + "_logic";
0097 
0098   G4LogicalVolume* pBoxLogic = new G4LogicalVolume(pBoxSolid, fpWater, boxNameLogic);
0099 
0100   std::sort(fMolecules.begin(), fMolecules.end());
0101 
0102   for (int i = 0, ie = fMolecules.size(); i < ie; ++i) {
0103     G4String name = fMolecules[i].fName;
0104     G4double radius = fMolecules[i].fRadius;
0105     G4double waterRadius = fMolecules[i].fRadiusWater;
0106     G4ThreeVector moleculePosition = fMolecules[i].fPosition;
0107 
0108     int copyNum = fMolecules[i].fCopyNumber;
0109 
0110     G4Orb* pMoleculeWaterSolid = nullptr;
0111     G4VSolid* pMoleculeWaterCutSolid = nullptr;
0112     G4LogicalVolume* pMoleculeWaterLogic = nullptr;
0113     G4VPhysicalVolume* pPhysicalVolumeWater = nullptr;
0114 
0115     G4double tolerence = 1e-4 * nm;
0116 
0117     if (waterRadius > tolerence) {
0118       G4String nameWaterSolid = name + "_water_solid";
0119       pMoleculeWaterSolid = new G4Orb(nameWaterSolid, waterRadius);
0120       pMoleculeWaterCutSolid =
0121         CreateCutSolid(pMoleculeWaterSolid, fMolecules[i], fMolecules, false);
0122 
0123       G4String nameWaterLogic = name + "_water_logic";
0124 
0125       pMoleculeWaterLogic = new G4LogicalVolume(pMoleculeWaterCutSolid, fpWater, nameWaterLogic);
0126       G4String nameWaterPhys = name + "_water";
0127       pPhysicalVolumeWater = new G4PVPlacement(0, moleculePosition, pMoleculeWaterLogic,
0128                                                nameWaterPhys, pBoxLogic, false, copyNum);
0129 
0130       auto it = fEnumMap.find(nameWaterPhys);
0131       if (it != fEnumMap.end()) {
0132         fGeometryMap.insert(std::make_pair(pPhysicalVolumeWater, it->second));
0133       }
0134       else {
0135         G4ExceptionDescription exceptionDescription;
0136         exceptionDescription << nameWaterPhys << " could not be exsited";
0137         G4Exception("DNAParser::CreateLogicVolume()", "DNAParser001", FatalException,
0138                     exceptionDescription);
0139       }
0140     }
0141     // Dna volume part
0142 
0143     G4Orb* pMoleculeSolid = nullptr;
0144     G4VSolid* pMoleculeCutSolid = nullptr;
0145     G4LogicalVolume* pMoleculeLogic = nullptr;
0146     G4VPhysicalVolume* pPhysicalVolumeMolecule = nullptr;
0147 
0148     G4String nameSolid = fMolecules[i].fName + "_solid";
0149     pMoleculeSolid = new G4Orb(nameSolid, radius);
0150 
0151     pMoleculeCutSolid = CreateCutSolid(pMoleculeSolid, fMolecules[i], fMolecules, true);
0152 
0153     G4String nameLogic = name + "_logic";
0154 
0155     pMoleculeLogic = new G4LogicalVolume(pMoleculeCutSolid, fpWater, nameLogic);
0156     if (waterRadius > tolerence) {
0157       G4ThreeVector position(0, 0, 0);
0158       std::string namePhys = name;
0159       pPhysicalVolumeMolecule = new G4PVPlacement(0, position, pMoleculeLogic, namePhys,
0160                                                   pMoleculeWaterLogic, false, copyNum);
0161 
0162       auto it = fEnumMap.find(namePhys);
0163       if (it != fEnumMap.end()) {
0164         fGeometryMap.insert(std::make_pair(pPhysicalVolumeMolecule, it->second));
0165       }
0166       else {
0167         G4ExceptionDescription exceptionDescription;
0168         exceptionDescription << namePhys << " could not be exsited";
0169         G4Exception("DNAParser::CreateLogicVolume()", "DNAParser002", FatalException,
0170                     exceptionDescription);
0171       }
0172     }
0173     else {
0174       G4ThreeVector position = moleculePosition;
0175       G4String namePhys = name;
0176       pPhysicalVolumeMolecule =
0177         new G4PVPlacement(0, position, pMoleculeLogic, namePhys, pBoxLogic, false, copyNum);
0178 
0179       auto it = fEnumMap.find(namePhys);
0180 
0181       if (it != fEnumMap.end()) {
0182         fGeometryMap.insert(std::make_pair(pPhysicalVolumeMolecule, it->second));
0183       }
0184       else {
0185         G4ExceptionDescription exceptionDescription;
0186         exceptionDescription << namePhys << " could not be exsited";
0187         G4Exception("DNAParser::CreateLogicVolume()", "DNAParser003", FatalException,
0188                     exceptionDescription);
0189       }
0190     }
0191   }
0192   fMolecules.clear();
0193   fRadiusMap.clear();
0194   fWaterRadiusMap.clear();
0195   return pBoxLogic;
0196 }
0197 
0198 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0199 
0200 void DNAParser::ParseFile(const std::string& fileName)
0201 {
0202   fMolecules.clear();
0203   fRadiusMap.clear();
0204   fWaterRadiusMap.clear();
0205 
0206   std::ifstream file(fileName.c_str());
0207 
0208   if (!file.is_open()) {
0209     G4ExceptionDescription exceptionDescription;
0210     exceptionDescription << fileName << "could not be opened";
0211     G4Exception("DNAParser::ParseFile()", "DNAParser002", FatalException, exceptionDescription);
0212   }
0213   std::string line;
0214   while (std::getline(file, line)) {
0215     if (line.empty()) continue;
0216     std::istringstream issLine(line);
0217     std::string firstItem;
0218     issLine >> firstItem;
0219 
0220     if (firstItem == "_Name") {
0221       G4String name = "";
0222       issLine >> name;
0223       fGeoName = name;
0224     }
0225     if (firstItem == "_Size") {
0226       G4double size;
0227       issLine >> size;
0228       size *= nm;
0229       fSize = size;
0230     }
0231     if (firstItem == "_Radius") {
0232       G4String name;
0233       issLine >> name;
0234       G4double radius;
0235       issLine >> radius;
0236       radius *= nm;
0237       G4double waterRadius;
0238       issLine >> waterRadius;
0239       waterRadius *= nm;
0240       fRadiusMap[name] = radius;
0241       fWaterRadiusMap[name] = waterRadius;
0242     }
0243     if (firstItem == "_pl") {
0244       std::string name;
0245       issLine >> name;
0246       G4String material;
0247       issLine >> material;
0248 
0249       G4int strand;
0250       issLine >> strand;
0251 
0252       G4int copyNumber;
0253       issLine >> copyNumber;
0254 
0255       G4double x;
0256       issLine >> x;
0257       x *= nm;
0258 
0259       G4double y;
0260       issLine >> y;
0261       y *= nm;
0262 
0263       G4double z;
0264       issLine >> z;
0265       z *= nm;
0266 
0267       Molecule molecule(name, copyNumber, G4ThreeVector(x, y, z), fRadiusMap[name],
0268                         fWaterRadiusMap[name], material, strand);
0269       fMolecules.push_back(molecule);
0270 
0271       auto itt = fEnumMap.find(name);
0272 
0273       if (itt != fEnumMap.end()) {
0274         if (itt->second != DNAVolumeType::phosphate1 && itt->second != DNAVolumeType::phosphate2) {
0275           if (itt->second == DNAVolumeType::deoxyribose1
0276               || itt->second == DNAVolumeType::deoxyribose2)
0277           {
0278             name = "Deoxyribose";
0279           }
0280           if (itt->second == DNAVolumeType::base_adenine) {
0281             name = "Adenine";
0282           }
0283           if (itt->second == DNAVolumeType::base_thymine) {
0284             name = "Thymine";
0285           }
0286           if (itt->second == DNAVolumeType::base_cytosine) {
0287             name = "Cytosine";
0288           }
0289           if (itt->second == DNAVolumeType::base_guanine) {
0290             name = "Guanine";
0291           }
0292           if (itt->second == DNAVolumeType::histone) {
0293             name = "Histone";
0294           }
0295 
0296           fpGun->AddMolecule(name, G4ThreeVector(x, y, z), 1 * picosecond);
0297         }
0298       }
0299       else {
0300         G4ExceptionDescription exceptionDescription;
0301         exceptionDescription << name << " could not be exsited";
0302         G4Exception("DNAParser::ParseFile()", "DNAParser005", FatalException, exceptionDescription);
0303       }
0304     }
0305   }
0306   file.close();
0307 }
0308 
0309 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0310 
0311 G4VSolid* DNAParser::CreateCutSolid(G4Orb* pSolidOrbRef, Molecule& molRef,
0312                                     std::vector<Molecule>& molList, G4bool in)
0313 {
0314   // The idea behing this method is to cut overlap volumes by selecting
0315   // one of them (the reference) and checking all the other volumes (the targets).
0316   // If a reference and a target volumes are close enough to overlap they will be cut.
0317   // The reference is already selected when we enter this method.
0318   // Use the tiny space to differentiate the frontiers (may not be necessary)
0319   G4double tinySpace = 0.001 * nm;
0320 
0321   G4SubtractionSolid* pSolidCut(NULL);
0322   G4bool isCutted = false;
0323   G4bool isOurVol = false;
0324   G4double radiusRef;
0325 
0326   if (molRef.fRadiusWater == 0) {
0327     radiusRef = molRef.fRadius;
0328   }
0329   else {
0330     radiusRef = molRef.fRadiusWater;
0331   }
0332 
0333   G4ThreeVector posRef = molRef.fPosition;
0334 
0335   if (std::abs(posRef.x()) + radiusRef > fSize / 2  // along x
0336       || std::abs(posRef.y()) + radiusRef > fSize / 2  // along y
0337       || std::abs(posRef.z()) + radiusRef > fSize / 2)  // along z
0338   {
0339     G4Box* solidBox = new G4Box("solid_box_for_cut", fSize / 2, fSize / 2, fSize / 2);
0340     G4ThreeVector posBox;
0341     G4RotationMatrix rotMat;
0342     rotMat.rotate(0, G4ThreeVector(0, 0, 1));
0343 
0344     if (std::abs(posRef.y() + radiusRef) > fSize / 2) {
0345       posBox = -posRef + G4ThreeVector(0, fSize, 0);
0346       if (!isCutted) {
0347         pSolidCut = new G4SubtractionSolid("solidCut", pSolidOrbRef, solidBox, &rotMat, posBox);
0348         isCutted = true;
0349       }
0350       else {
0351         pSolidCut = new G4SubtractionSolid("solidCut", pSolidCut, solidBox, &rotMat, posBox);
0352       }
0353     }
0354     // Down
0355     if (std::abs(posRef.y() - radiusRef) > fSize / 2) {
0356       posBox = -posRef + G4ThreeVector(0, -fSize, 0);
0357 
0358       if (!isCutted) {
0359         pSolidCut = new G4SubtractionSolid("solidCut", pSolidOrbRef, solidBox, &rotMat, posBox);
0360         isCutted = true;
0361       }
0362       else {
0363         pSolidCut = new G4SubtractionSolid("solidCut", pSolidCut, solidBox, &rotMat, posBox);
0364       }
0365     }
0366     // Left
0367     if (std::abs(posRef.x() + radiusRef) > fSize / 2) {
0368       posBox = -posRef + G4ThreeVector(fSize, 0, 0);
0369       if (!isCutted) {
0370         pSolidCut = new G4SubtractionSolid("solidCut", pSolidOrbRef, solidBox, &rotMat, posBox);
0371         isCutted = true;
0372       }
0373       else {
0374         pSolidCut = new G4SubtractionSolid("solidCut", pSolidCut, solidBox, &rotMat, posBox);
0375       }
0376     }
0377 
0378     // Right
0379     if (std::abs(posRef.x() - radiusRef) > fSize / 2) {
0380       posBox = -posRef + G4ThreeVector(-fSize, 0, 0);
0381       if (!isCutted) {
0382         pSolidCut = new G4SubtractionSolid("solidCut", pSolidOrbRef, solidBox, &rotMat, posBox);
0383         isCutted = true;
0384       }
0385       else {
0386         pSolidCut = new G4SubtractionSolid("solidCut", pSolidCut, solidBox, &rotMat, posBox);
0387       }
0388     }
0389     // Forward
0390     if (std::abs(posRef.z() + radiusRef) > fSize / 2) {
0391       posBox = -posRef + G4ThreeVector(0, 0, fSize);
0392       if (!isCutted) {
0393         pSolidCut = new G4SubtractionSolid("solidCut", pSolidOrbRef, solidBox, &rotMat, posBox);
0394         isCutted = true;
0395       }
0396       else {
0397         pSolidCut = new G4SubtractionSolid("solidCut", pSolidCut, solidBox, &rotMat, posBox);
0398       }
0399     }
0400 
0401     // Backward
0402     if (std::abs(posRef.z() - radiusRef) > fSize / 2) {
0403       posBox = -posRef + G4ThreeVector(0, 0, -fSize);
0404       if (!isCutted) {
0405         pSolidCut = new G4SubtractionSolid("solidCut", pSolidOrbRef, solidBox, &rotMat, posBox);
0406         isCutted = true;
0407       }
0408       else {
0409         pSolidCut = new G4SubtractionSolid("solidCut", pSolidCut, solidBox, &rotMat, posBox);
0410       }
0411     }
0412   }
0413 
0414   for (int i = 0, ie = molList.size(); i < ie; ++i) {
0415     G4ThreeVector posTar = molList[i].fPosition;
0416     G4double rTar = posRef.z();
0417     G4double zTar = posTar.z();
0418 
0419     if (zTar > rTar + 20 * nm) {
0420       break;
0421     }
0422     else if (zTar < rTar - 20 * nm) {
0423       continue;
0424     }
0425 
0426     G4double radiusTar;
0427     if (molList[i].fRadiusWater == 0) {
0428       radiusTar = molList[i].fRadius;
0429     }
0430     else {
0431       radiusTar = molList[i].fRadiusWater;
0432     }
0433 
0434     G4double distance = std::abs((posRef - posTar).getR());
0435 
0436     if (distance == 0 && !isOurVol) {
0437       isOurVol = true;
0438       continue;
0439     }
0440     else if (distance == 0 && isOurVol) {
0441       G4ExceptionDescription exceptionDescription;
0442       exceptionDescription << "CreateCutSolid: Two volumes "
0443                            << "are placed at the same position.";
0444       G4Exception("DNAParser::CreateCutSolid()", "DNAParser004", FatalException,
0445                   exceptionDescription);
0446     }
0447     else if (distance <= radiusRef + radiusTar) {
0448       G4Box* solidBox = new G4Box("solid_box_for_cut", 2 * radiusTar, 2 * radiusTar, 2 * radiusTar);
0449       G4ThreeVector diff = posTar - posRef;
0450       G4double d =
0451         (std::pow(radiusRef, 2) - std::pow(radiusTar, 2) + std::pow(distance, 2)) / (2 * distance)
0452         + solidBox->GetZHalfLength() - tinySpace;
0453       if (in) {
0454         d -= 2 * tinySpace;
0455       }
0456       G4ThreeVector pos = d * (diff / diff.getR());
0457       G4double phi = std::acos(pos.getZ() / pos.getR());
0458       G4double theta = std::acos(pos.getX() / (pos.getR() * std::cos(CLHEP::pi / 2. - phi)));
0459 
0460       if (pos.getY() < 0) {
0461         theta = -theta;
0462       }
0463 
0464       G4ThreeVector rotAxisForPhi(1 * nm, 0., 0.);
0465       rotAxisForPhi.rotateZ(theta + CLHEP::pi / 2.);
0466 
0467       G4RotationMatrix* rotMat = new G4RotationMatrix;
0468       rotMat->rotate(-phi, rotAxisForPhi);
0469 
0470       G4ThreeVector rotZAxis(0., 0., 1 * nm);
0471       rotMat->rotate(theta, rotZAxis);
0472 
0473       if (!isCutted) {
0474         pSolidCut = new G4SubtractionSolid("solidCut", pSolidOrbRef, solidBox, rotMat, pos);
0475       }
0476       else {
0477         pSolidCut = new G4SubtractionSolid("solidCut", pSolidCut, solidBox, rotMat, pos);
0478       }
0479       isCutted = true;
0480     }
0481   }
0482 
0483   if (isCutted) {
0484     return pSolidCut;
0485   }
0486   else {
0487     return pSolidOrbRef;
0488   }
0489 }
0490 
0491 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0492 
0493 void DNAParser::EnumParser()
0494 {
0495   fEnumMap["deoxyribose1"] = deoxyribose1;
0496   fEnumMap["phosphate1"] = phosphate1;
0497   fEnumMap["deoxyribose2"] = deoxyribose2;
0498   fEnumMap["phosphate2"] = phosphate2;
0499 
0500   fEnumMap["base_cytosine"] = base_cytosine;
0501   fEnumMap["base_guanine"] = base_guanine;
0502   fEnumMap["base_thymine"] = base_thymine;
0503   fEnumMap["base_adenine"] = base_adenine;
0504 
0505   fEnumMap["deoxyribose1_water"] = deoxyribose1_water;
0506   fEnumMap["phosphate1_water"] = phosphate1_water;
0507   fEnumMap["deoxyribose2_water"] = deoxyribose2_water;
0508   fEnumMap["phosphate2_water"] = phosphate2_water;
0509 
0510   fEnumMap["base_adenine_water"] = base_adenine_water;
0511   fEnumMap["base_guanine_water"] = base_guanine_water;
0512   fEnumMap["base_cytosine_water"] = base_cytosine_water;
0513   fEnumMap["base_thymine_water"] = base_thymine_water;
0514 
0515   fEnumMap["histone"] = histone;
0516   fEnumMap["physWorld"] = physWorld;
0517   fEnumMap["VoxelStraight"] = VoxelStraight;
0518 }