Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/examples/advanced/dna/dsbandrepair/analysis/dnadamage/src/ScanDamage.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  1 //
  2 // ********************************************************************
  3 // * License and Disclaimer                                           *
  4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
  6 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
  7 // * conditions of the Geant4 Software License,  included in the file *
  8 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
  9 // * include a list of copyright holders.                             *
 10 // *                                                                  *
 11 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file  LICENSE  and URL above *
 16 // * for the full disclaimer and the limitation of liability.         *
 17 // *                                                                  *
 18 // * This  code  implementation is the result of  the  scientific and *
 19 // * technical work of the GEANT4 collaboration.                      *
 20 // * By using,  copying,  modifying or  distributing the software (or *
 21 // * any work based  on the software)  you  agree  to acknowledge its *
 22 // * use  in  resulting  scientific  publications,  and indicate your *
 23 // * acceptance of all terms of the Geant4 Software license.          *
 24 // ********************************************************************
 25 //
 26 //
 27 /// \file ScanDamage.cc
 28 /// \brief Implementation of the ScanDamage class
 29 
 30 #include "ScanDamage.hh"
 31 #include "ParametersParser.hh"
 32 
 33 #include "TSystemDirectory.h"
 34 #include "TFile.h"
 35 #include "TTree.h"
 36 #include "TRandom.h"
 37 
 38 
 39 #include <iostream>
 40 #include <fstream>
 41 #include <sstream>
 42 #include <iostream>
 43 #include <filesystem>
 44 namespace fs = std::filesystem;
 45 TRandom gRandomGen; 
 46 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
 47 
 48 ScanDamage::ScanDamage(): fSkipScanningIndirectDamage(false)
 49 {
 50     fThresholdEnergy = 17.5; //eV
 51     fEdepSumInNucleus = 0;
 52     fProbabilityForIndirectSB = 0.40; // 40%
 53 }
 54 
 55 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
 56 
 57 std::map<unsigned int,std::map<unsigned int,std::vector<Damage> > > ScanDamage::ExtractDamage(){
 58     ReadCellandVoxelDefFilePaths();
 59     fMergedTables.clear();
 60     fDamage.clear();
 61     RetrieveVoxelBp();
 62     FillVoxelData();
 63     ScanDamageFromPhys();
 64     if (!fSkipScanningIndirectDamage) ScanDamageFromChem();
 65     MergeDamageFromPhysChem();
 66     for (const auto& [pChrom,table] : fMergedTables) {
 67         unsigned int evt;
 68         unsigned int strand;
 69         ullint cpyNb;
 70         unsigned int isBase;
 71         double time;
 72         double edep;
 73         double origin;
 74         Damage::DamageType pType;
 75         Damage::DamageCause pOrigin;
 76         std::map<unsigned int,std::vector<Damage> > perChromoDamage;
 77         for (const auto& v : table) {
 78             evt = v.at(0);
 79             strand = v.at(1);
 80             cpyNb = v.at(2);
 81             isBase = v.at(3);
 82             time = v.at(4);
 83             edep = v.at(5);
 84             origin = v.at(6);
 85             if(isBase==0)
 86                 pType=Damage::DamageType::fBackbone;
 87             else
 88                 pType=Damage::DamageType::fBase;
 89             if(origin==0)
 90                 pOrigin=Damage::DamageCause::fDirect;
 91             else
 92                 pOrigin=Damage::DamageCause::fIndirect;
 93             if (perChromoDamage.find(evt) == perChromoDamage.end()) {
 94                 std::vector<Damage> dm{Damage(pType,pChrom,evt,strand,cpyNb,Position(0,0,0),
 95                                             pOrigin,Damage::DamageChromatin::fUnspecified)};
 96                 perChromoDamage.insert({evt,dm});
 97             } else perChromoDamage[evt].push_back(Damage(pType,pChrom,evt,strand,cpyNb,Position(0,0,0),
 98                                             pOrigin,Damage::DamageChromatin::fUnspecified));
 99         }
100         fDamage.insert({pChrom,perChromoDamage});
101     }
102     return fDamage;
103 }
104 
105 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
106 
107 void ScanDamage::RetrieveVoxelBp()
108 {
109     fBpPerVoxel.clear();
110     
111     for (const auto & entry : fVoxelDefFilesList) {
112         std::ifstream file(entry);
113         if(!file.good() )
114         {
115             std::cerr<<"**** Fatal Error *****"<<std::endl;
116             std::cerr<<"ScanDamage::RetrieveVoxelBp: No file named "<<entry<<std::endl;
117             std::cerr<<"*************** *****"<<std::endl;
118             exit(EXIT_FAILURE);
119         }
120         std::string voxelName = "noName";
121         std::string line;
122         bool foundName = false;
123         bool foundNumOfBp = false;
124         while(std::getline(file, line)
125             && !foundNumOfBp)
126         {
127             std::istringstream iss(line);
128             std::string flag;
129             iss >> flag;
130             std::string charac;
131             iss >> charac;
132             // Look for the name of the voxel
133             if(flag=="_Name")
134             {
135                 voxelName = charac;
136                 foundName = true;
137             }
138             // Look for the flag "_Number"
139             // And the characteristic "voxelBasePair"
140             if(flag=="_Number" && charac=="voxelBasePair")
141             {
142                 int numOfBp;
143                 iss >> numOfBp;
144                 if(!foundName)
145                 {
146                     std::cerr<<"*** Fatal Error ***"<<std::endl;
147                     std::cerr<<"ScanDamage::RetrieveVoxelBp: The number of bp was found before the name "
148                     <<"of the voxel... This is an unexpected case."<<std::endl;
149                     std::cerr<<"******"<<std::endl;
150                     exit(EXIT_FAILURE);
151                 }
152                 else
153                 {
154                     fBpPerVoxel[voxelName] = numOfBp;
155                     std::cout<<voxelName<<" has "<<numOfBp<<" bp"<<std::endl;
156                     foundNumOfBp = true;
157                 }
158             }
159         }
160         file.close();
161     }
162     
163     if (fBpPerVoxel.size() == 0) {
164         std::cerr<<"**** Fatal Error *****"<<std::endl;
165         std::cerr<<"ScanDamage::RetrieveVoxelBp: No Bp found in voxel definition files. \n Or make"
166         <<" sure that file imp.info exists in working directory!"<<std::endl;
167         std::cerr<<"*************** *****"<<std::endl;
168         exit(EXIT_FAILURE);
169     }
170 }
171 
172 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
173 
174 void ScanDamage::FillVoxelData()
175 {   
176     std::ifstream file(fCellDefFilePath);
177     if(!file.good() )
178     {
179         std::cerr<<"**** Fatal Error *****"<<std::endl;
180         std::cerr<<"FillVoxelData: No file named "<<fCellDefFilePath<<std::endl;
181         std::cerr<<"*************** *****"<<std::endl;
182         exit(EXIT_FAILURE);
183     }
184     ullint bpCount = 0;
185     unsigned int voxelCount = 0;
186     int chromo_previous = 0;
187     // Read the file line by line
188     std::string line;
189     while(std::getline(file, line) )
190     {
191         std::istringstream iss(line);
192         std::string flag;
193         iss >> flag;
194         // If the flag correspond to the placement of a voxel
195         if(flag == "_pl")
196         {
197             std::string voxelName;
198             iss >> voxelName;
199             int chromo;
200             iss >> chromo;
201             int domain;
202             iss >> domain;
203             // If we change of chromosome then reset the number of bp.
204             // Each chromosome starts at 0 bp.
205             if(chromo != chromo_previous)
206             {
207                 bpCount = 0;
208                 chromo_previous = chromo;
209             }
210             // Fill the data structure
211             fVoxels.push_back( VoxelData(chromo, domain, bpCount) );
212             int numBpinthisvoxel = int(fBpPerVoxel[voxelName]);
213             bpCount += numBpinthisvoxel;
214             if (fChromosomeBpMap.find(chromo) == fChromosomeBpMap.end()) {
215                 fChromosomeBpMap.insert({chromo,numBpinthisvoxel});
216             } else {
217                 fChromosomeBpMap[chromo] += numBpinthisvoxel;
218             }
219             voxelCount++;
220         }
221     }
222     file.close();
223     
224 
225     if (fVoxels.size() == 0) {
226         std::cerr<<"**** Fatal Error *****"<<std::endl;
227         std::cerr<<"ScanDamage::FillVoxelData: NofVoxels info found in files "<<fCellDefFilePath<<std::endl;
228         std::cerr<<"*************** *****"<<std::endl;
229         exit(EXIT_FAILURE);
230     }
231     std::cout<<"Num of voxels: "<< fVoxels.size()<<" placed in Cell Nucleus."<<std::endl;
232     std::cout<<"=====Choromosome sizes====="<<std::endl;
233     std::cout<<"Chromosome ID\t Number of Bp"<<std::endl;
234     for (auto const& [chrom, nBp] : fChromosomeBpMap) {
235          std::cout<<chrom<< "\t"<<nBp<<std::endl;
236     }
237     std::cout<<"==========================="<<std::endl;
238 }
239 
240 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
241 
242 void ScanDamage::ScanDamageFromPhys()
243 {
244     std::cout<<"===== Start Scanning Damages From Phys =====\n";
245     fEdepSumInNucleus = 0;
246     fphysTables.clear();
247     fphysSlectedTables.clear();
248     fs::path currentP{"phys_output"};
249     fs::file_status s = fs::file_status{};
250     auto isExist = fs::status_known(s) ? fs::exists(s) : fs::exists(currentP);
251     if (isExist) {
252         bool isFoundRootFiles = false;
253         for (const auto entry : fs::directory_iterator(currentP)) {
254             if (entry.path().extension() == ".root") {
255                 std::cout <<"ScanDamageFromPhys(): Processing file: "<< entry.path().filename()<< std::endl;
256                 AnaPhysRootFile(entry.path());
257                 if (!isFoundRootFiles) isFoundRootFiles=true;
258             }
259         }
260         if (!isFoundRootFiles) {
261             std::cout<<"=====>> No root files found in folder \"phys_ouput\"!!! Skip Scanning Damages From Phys =====\n";
262         }
263         if (fphysTables.size() > 0) {
264             SortPhysTableWithSelection();
265         }
266     } else {
267         std::cout<<"=====>> Cannot find folder \"phys_ouput\"!!! Skip Scanning Damages From Phys =====\n";
268     }
269 
270     std::cout<<"===== End Scanning Damages From Phys =====\n";
271 }
272 
273 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
274 
275 void ScanDamage::ScanDamageFromChem()
276 {
277     std::cout<<"===== Start Scanning Damages From Chem =====\n";
278     std::string fChemOutFolderName = ParametersParser::Instance()->GetChemOutFolderName();
279     if (fChemOutFolderName == "") fChemOutFolderName = "chem_output";
280     fs::path currentP{fChemOutFolderName};
281     fs::file_status s = fs::file_status{};
282     auto isExist = fs::status_known(s) ? fs::exists(s) : fs::exists(currentP);
283     if (isExist) {
284         bool isFoundRootFiles = false;
285         for (const auto entry : fs::directory_iterator(currentP)) {
286             if (entry.path().extension() == ".root") {
287                 AnaChemRootFile(entry);
288                 if (!isFoundRootFiles) isFoundRootFiles=true;
289             }
290         }
291         if (!isFoundRootFiles) {
292             std::cout<<"=====>> No root files found in folder \""<<fChemOutFolderName<<"\"!!! Skip Scanning Damages From Chem =====\n";
293             fSkipScanningIndirectDamage = true;
294         }
295         if (fchemTables.size() > 0) {
296             SortChemTableWithSelection();
297         }
298     } else {
299         std::cout<<"=====>> Cannot find folder \""<<fChemOutFolderName<<"\"!!! Skip Scanning Damages From Chem =====\n";
300         fSkipScanningIndirectDamage = true;
301     }
302     
303     std::cout<<"===== End Scanning Damages From Chem =====\n";
304 }
305 
306 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
307 
308 void ScanDamage::AnaPhysRootFile(const std::string fileName)
309 {
310     TFile* f = new TFile(fileName.c_str());
311     if(f->IsZombie() ){
312         // File is corrupted
313         std::cerr<<"*********** Warning *************"<<std::endl;
314         std::cerr<<"The file "<<fileName<<" seems to be corrupted..."<<std::endl;
315         std::cerr<<"We will skip it."<<std::endl;
316         std::cerr<<"**********************************"<<std::endl;
317         return;
318     }
319     AnaPhysRootTree1(f);
320     AnaPhysRootTree2(f);
321     f->Close();
322 }
323 
324 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
325 
326 void ScanDamage::AnaChemRootFile(fs::directory_entry entry)
327 {
328     std::string fnameWithoutExtension = entry.path().stem().string();
329     auto [eventNumber, voxelNumber] = GetEventNberAndVoxelNberFromChemRoot(fnameWithoutExtension);
330     
331     // Voxel data retrieval
332     VoxelData& voxelData = fVoxels.at(voxelNumber);
333 
334     int chromo = voxelData.fChromosome;
335     ullint firstBpNum = voxelData.fFirstBpCopyNum;
336     // *******************
337     // Analyse of the ntuple to detect SB and associate them with a bpNumCorrected
338     // *******************
339 
340     // Load the file, the directory and the ntuple
341     TFile f(entry.path().c_str());
342     if(f.IsZombie() ){
343         corruptedFiles++;
344         // File is corrupted
345         std::cerr<<"*********** Warning *************"<<std::endl;
346         std::cerr<<"The file "<<entry.path().string()<<" seems to be corrupted..."<<std::endl;
347         std::cerr<<"We will skip it."<<std::endl;
348         std::cerr<<"Number of corrupted files: "<< corruptedFiles<<std::endl;
349         std::cerr<<"**********************************"<<std::endl;
350     } else {
351         TDirectoryFile *d = dynamic_cast<TDirectoryFile*> (f.Get("ntuple") );
352         TTree* chemTree = (TTree*) d->Get("ntuple_2");
353 
354         if( (int) chemTree->GetEntries() >0)
355         {
356             int strand;
357             int copyNumber;
358             double xp;
359             double yp;
360             double zp;
361             double time;
362             int base;
363             chemTree->SetBranchAddress("strand", &strand);
364             chemTree->SetBranchAddress("copyNumber", &copyNumber);
365             chemTree->SetBranchAddress("xp", &xp);
366             chemTree->SetBranchAddress("yp", &yp);
367             chemTree->SetBranchAddress("zp", &zp);
368             chemTree->SetBranchAddress("time", &time);
369             chemTree->SetBranchAddress("base", &base);
370             unsigned int entryNumber = (int) chemTree->GetEntries();
371             for (unsigned int e=0;e<entryNumber;e++)
372             {
373                 chemTree->GetEntry(e);
374                 ullint cpNumCorrected = firstBpNum+int(copyNumber);
375                 std::vector<ullint> newLine{ 
376                     (ullint)eventNumber,(ullint)strand,cpNumCorrected,
377                     (ullint)base,(ullint)(time*1000000)};
378                 auto itr = fchemTables.find(chromo);
379                 if ( itr == fchemTables.end()) {
380                     Table tbforThisChro{newLine};
381                     fchemTables.insert({chromo,tbforThisChro});
382                 } else (itr->second).push_back(newLine);
383             }
384         }
385     }//
386 }
387 
388 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
389 
390 std::tuple<unsigned int, unsigned int> ScanDamage::GetEventNberAndVoxelNberFromChemRoot(
391     const std::string fileNameWithoutExtension)
392 {
393     unsigned int evnN, volxelN;
394     auto fristPos = fileNameWithoutExtension.find_first_of("_");
395     auto secondPos = fileNameWithoutExtension.substr(fristPos+1).find_first_of("_");
396     auto lastPos = fileNameWithoutExtension.find_last_of("_");
397     evnN = std::stoul(fileNameWithoutExtension.substr(fristPos+1,secondPos));
398     volxelN = std::stoul(fileNameWithoutExtension.substr(lastPos+1));
399     return  {evnN, volxelN};
400 }
401 
402 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
403 
404 void ScanDamage::AnaPhysRootTree1(TFile* f)
405 {
406     TDirectoryFile* d = dynamic_cast<TDirectoryFile*> (f->Get("ntuple") );
407     TTree* tPhys = dynamic_cast<TTree*> (d->Get("ntuple_1") );
408 
409     if( tPhys->GetEntries()  > 0)
410         {
411         int flagParticle;
412         int flagParentID;
413         int flagProcess;
414         double x;
415         double y;
416         double z;
417         double edep;
418         int eventNumber;
419         int volumeName;
420         int copyNumber;
421         int lastMetVoxelCopyNum;
422 
423         tPhys->SetBranchAddress("flagParticle", &flagParticle);
424         tPhys->SetBranchAddress("flagParentID", &flagParentID);
425         tPhys->SetBranchAddress("flagProcess", &flagProcess);
426         tPhys->SetBranchAddress("x", &x);
427         tPhys->SetBranchAddress("y", &y);
428         tPhys->SetBranchAddress("z", &z);
429         tPhys->SetBranchAddress("edep", &edep);
430         tPhys->SetBranchAddress("eventNumber", &eventNumber);
431         tPhys->SetBranchAddress("volumeName", &volumeName);
432         tPhys->SetBranchAddress("copyNumber", &copyNumber);
433         tPhys->SetBranchAddress("lastMetVoxelCopyNum", &lastMetVoxelCopyNum);
434 
435         unsigned int entryNumber =  tPhys->GetEntries() ;
436 
437         // Loop on all the "lines" (ie entry) of the ntuple
438         for(unsigned int e=0; e<entryNumber; e++)
439         {
440             // Set all the variables to the values corresponding to the entry number
441             tPhys->GetEntry(e);
442             // Check if the process is an ionisation
443             // Only ionisation should trigger the removal of a DNA molecule from the chemical step
444             if(flagProcess == 13 // e-_DNAIonisation
445                     || flagProcess == 113 // e-_DNAPTBIonisation
446                     || flagProcess == 18 // proton_DNAIonisation
447                     || flagProcess == 21 // hydrogen_DNAIonisation
448                     || flagProcess == 24 // alpha_DNAIonisation
449                     || flagProcess == 27 // alpha+_DNAIonisation
450                     || flagProcess == 31 // helium_DNAIonisation
451                     || flagProcess == 12 // e-_DNAExcitation
452                     || flagProcess == 112 // e-_DNAPTBExcitation
453                     || flagProcess == 15 // e-_DNAVibExcitation
454                     || flagProcess == 17 // proton_DNAExcitation
455                     || flagProcess == 20 // hydrogen_DNAExcitation
456                     || flagProcess == 23 // alpha_DNAExcitation
457                     || flagProcess == 26 // alpha+_DNAExcitation
458                     || flagProcess == 30 // helium_DNAExcitation
459                     ) {
460                 // Check the interaction happened in a dna molecule or its hydration shell
461                 if(volumeName == 1 // d1
462                         || volumeName == 11 // p1
463                         || volumeName == 2 // d2
464                         || volumeName == 22 // p2
465                         || volumeName == 7 // d1_w
466                         || volumeName == 71 // p1_w
467                         || volumeName == 8 // d2_w
468                         || volumeName == 81 // p2_w
469                         )
470                 {
471                     // *************
472 
473                     // Retrieve the voxel copy number
474                     double voxelCopyNumber  = lastMetVoxelCopyNum;
475                     if (voxelCopyNumber >= 0 && voxelCopyNumber<fVoxels.size()){
476                         // Chromosome, domain and firstNucleotideNum
477                         const VoxelData& voxelData = fVoxels.at(size_t(voxelCopyNumber) );
478                         int chromo = voxelData.fChromosome;
479                         int domain = voxelData.fDomain;
480                         ullint firstBpCN = voxelData.fFirstBpCopyNum;
481                         ullint cpNumCorrected = firstBpCN+int(copyNumber);
482 
483                         // Get the event number
484                         double eventNum = eventNumber;
485 
486                         // Determine the strand
487                         double strand (-1);
488                         if(volumeName==1
489                                 || volumeName==11
490                                 || volumeName==7
491                                 || volumeName==71
492                                 || volumeName==6 // ade
493                                 || volumeName==9 // ade
494                                 || volumeName==4 // gua
495                                 || volumeName==10) // gua
496                             strand = 1;
497                         else if(volumeName==2
498                                 || volumeName==22
499                                 || volumeName==8
500                                 || volumeName==81
501                                 || volumeName==5 // thy
502                                 || volumeName==12 // thy
503                                 || volumeName==3 // cyto
504                                 || volumeName==13) // cyto
505                             strand = 2;
506                         // Check if the chromo has already been registered
507                         std::vector<ullint> newLine{ 
508                             (ullint)eventNum,(ullint)strand,cpNumCorrected,
509                             (ullint)volumeName,(ullint)flagProcess,(ullint)(edep*1000000)};
510                             // *1000000 in edep is taken back after. This is done 
511                             // because the number is "unsigned long long int" instead of "double".
512                         auto itr = fphysTables.find(chromo);
513                         if ( itr == fphysTables.end()) {
514                             Table tbforThisChro{newLine};
515                             fphysTables.insert({chromo,tbforThisChro});
516                         } else (itr->second).push_back(newLine);
517                     }
518                 }
519             }
520         }
521     }
522 }
523 
524 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
525 
526 void ScanDamage::AnaPhysRootTree2(TFile* f)
527 {
528     TDirectoryFile* d2 = dynamic_cast<TDirectoryFile*> (f->Get("ntuple") );
529     TTree* tPhys2 = dynamic_cast<TTree*> (d2->Get("ntuple_3") );
530 
531     if( int(tPhys2->GetEntries() ) > 0)
532     {
533         double edep;
534         int eventNumber;
535 
536         tPhys2->SetBranchAddress("edep", &edep);
537         tPhys2->SetBranchAddress("eventNumber", &eventNumber);
538 
539         unsigned int entryNumber = int( tPhys2->GetEntries() );
540 
541         // Loop on all the "lines" (ie entry) of the ntuple
542         for(unsigned int e=0; e<entryNumber; e++)
543         {
544             tPhys2->GetEntry(e);
545             fEdepSumInNucleus += edep;
546         }
547     }
548 }
549 
550 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
551 
552 void ScanDamage::SortPhysTableWithSelection()
553 {
554     for(const auto [chrom, physTable] : fphysTables)
555     {
556         // Final table
557         Table physTableWithSelection;
558 
559         std::map<ullint,std::map<ullint,std::map<ullint, ullint > > > energyMap;
560         
561         // Loop on all the lines of the table
562         for(unsigned int line=0, eline=physTable.size(); line<eline; ++line)
563         {
564             ullint eventNum = physTable[line][0];
565             ullint strand = physTable[line][1];
566             ullint copyNumber = physTable[line][2];
567             ullint volumeFlag = physTable[line][3];
568             ullint processFlagr = physTable[line][4];
569             ullint energy = physTable[line][5];
570 
571             // Cumulate the energy value
572             energyMap[eventNum][strand][copyNumber] += energy;
573         }
574 
575         int notDuplicatedLine = 0;
576 
577         // Loop on all the events
578         std::map<ullint, std::map<ullint, std::map<ullint, ullint> > >::iterator iit = energyMap.begin();
579         std::map<ullint, std::map<ullint, std::map<ullint, ullint> > >::iterator iite = energyMap.end();
580         for(; iit!=iite;++iit)
581         {
582             ullint eventNum = iit->first;
583 
584             // Loop on all the strands
585             std::map<ullint, std::map<ullint, ullint> >::iterator itt = iit->second.begin();
586             std::map<ullint, std::map<ullint, ullint> >::iterator itte = iit->second.end();
587             for(; itt!=itte;++itt)
588             {
589                 ullint strand = itt->first;
590                 // Loop on all the copy numbers
591                 std::map<ullint, ullint>::iterator ittt = itt->second.begin();
592                 std::map<ullint, ullint>::iterator ittte = itt->second.end();
593                 for(; ittt!=ittte;++ittt)
594                 {
595                     ullint copyNumber = ittt->first;
596                     double currentE = double(ittt->second) / 1000000; // eV
597                     // Energy condition(s) are set here
598                     bool fill = false;                  
599                      // Threshold condition
600                      if(currentE < fThresholdEnergy)
601                           fill=false;
602                      else
603                           fill=true;
604 
605                     if(fill)
606                     {
607                         // Add a line
608                         physTableWithSelection.push_back(std::vector<ullint>());
609                         // Fill the line
610                         physTableWithSelection[notDuplicatedLine].push_back(eventNum);
611                         physTableWithSelection[notDuplicatedLine].push_back(strand);
612                         physTableWithSelection[notDuplicatedLine].push_back(copyNumber);
613                         physTableWithSelection[notDuplicatedLine].push_back(0);
614                         physTableWithSelection[notDuplicatedLine].push_back(0);
615                         physTableWithSelection[notDuplicatedLine].push_back((ullint)(currentE*1000000) );
616                         physTableWithSelection[notDuplicatedLine].push_back(0);
617                         ++notDuplicatedLine;
618                     }
619                 }
620             }
621         }
622         // *******************************************
623         // Print the "physTableWithSelection" table for the current chromosome
624         // *******************************************
625         std::cout << "### Phys SB for chromosome "<<chrom<<" : " << physTableWithSelection.size() << " ###" << std::endl;
626         if (physTableWithSelection.size()>0) fphysSlectedTables.insert({chrom,physTableWithSelection});
627     }
628     fphysTables.clear();//Free memory
629 }
630 
631 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
632 
633 void ScanDamage::SortChemTableWithSelection()
634 {
635     for (const auto& [chromo,chemTable] : fchemTables)
636     {
637         // Final table
638         Table chemTableWithSelection;
639         
640         int notDuplicatedLine = 0;
641 
642         for(unsigned int line=0, eline=chemTable.size(); line<eline; ++line)
643         {
644             ullint eventNum = chemTable[line][0];
645             ullint strand = chemTable[line][1];
646             ullint copyNumber = chemTable[line][2];
647             ullint base = chemTable[line][3];
648             ullint time = chemTable[line][4];
649         
650         // Random number between 0 and <1
651       if (base==1) {
652                 // Add a line
653                 chemTableWithSelection.push_back(std::vector<ullint>());
654                 // Fill the line
655                 chemTableWithSelection[notDuplicatedLine].push_back(eventNum);
656                 chemTableWithSelection[notDuplicatedLine].push_back(strand);
657                 chemTableWithSelection[notDuplicatedLine].push_back(copyNumber);
658                 chemTableWithSelection[notDuplicatedLine].push_back(base);
659                 chemTableWithSelection[notDuplicatedLine].push_back(time);
660                 chemTableWithSelection[notDuplicatedLine].push_back(0);
661                 chemTableWithSelection[notDuplicatedLine].push_back(1);              
662                 ++notDuplicatedLine;
663       }
664       else { 
665           //double r = double(std::rand() ) / RAND_MAX;
666                 double r = gRandomGen.Rndm(); 
667                 //std::cout<<r<<std::endl;
668           if(r <= fProbabilityForIndirectSB){
669                     // Add a line
670                     chemTableWithSelection.push_back(std::vector<ullint>());
671                     // Fill the line
672                     chemTableWithSelection[notDuplicatedLine].push_back(eventNum);
673                     chemTableWithSelection[notDuplicatedLine].push_back(strand);
674                     chemTableWithSelection[notDuplicatedLine].push_back(copyNumber);
675                     chemTableWithSelection[notDuplicatedLine].push_back(base);
676                     chemTableWithSelection[notDuplicatedLine].push_back(time);
677                     chemTableWithSelection[notDuplicatedLine].push_back(0);
678                     chemTableWithSelection[notDuplicatedLine].push_back(1);                          
679                     ++notDuplicatedLine;
680                 }
681           }
682         }     
683         if (chemTableWithSelection.size() > 0) fchemSlectedTables.insert({chromo,chemTableWithSelection});
684   }
685     fchemTables.clear();//free memory
686 }
687 
688 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
689 
690 void ScanDamage::MergeDamageFromPhysChem()
691 {
692     for(int  chromo=0; chromo<46; chromo++)
693     {
694         // *****************************
695         // Add one table after the other
696         // *****************************
697 
698         // MergedTable to be built
699         Table mergedTable;
700 
701         auto itr = fphysSlectedTables.find(chromo);
702         if(itr != fphysSlectedTables.end())
703         {
704             Table physTable= itr->second;
705             for(auto const& vec : physTable) mergedTable.push_back(vec);
706         }
707         itr = fchemSlectedTables.find(chromo);
708         if(itr != fchemSlectedTables.end())
709         {
710             Table chemTable = itr->second;
711             for(auto const& vec : chemTable) mergedTable.push_back(vec);
712         }
713 
714         // *******************************************
715         // Sort the merged table to put the event in the correct order
716         // *******************************************
717         Trier tri;
718         Table::iterator it = mergedTable.begin();
719         Table::iterator ite = mergedTable.end();
720         std::sort(it, ite, tri);
721 
722         // *******************************************
723         // Delete duplicate SB
724         // *******************************************
725 
726         std::map<ullint,std::map<ullint,std::map<ullint,std::map<ullint,std::vector<ullint>>>>> removeDuplicateValueMap;
727 
728         // Put all the values of the mergedTable in the map created just above.
729         // Loop on all the lines of the mergedTable
730         for(unsigned int line=0; line<mergedTable.size(); ++line)
731         {
732             ullint eventNum = mergedTable[line][0];
733             ullint strand = mergedTable[line][1];
734             ullint copyNumber = mergedTable[line][2];
735             ullint base = mergedTable[line][3];
736             std::vector<ullint> lineV;
737             // If more elements are presents, add them here
738             int lineSize = mergedTable[line].size();
739             if(lineSize > 4)
740             {
741                 for(int i=4; i<lineSize; i++)
742                 {
743                     lineV.push_back(mergedTable[line][i]);
744                 }
745                 removeDuplicateValueMap[eventNum][strand][copyNumber][base]=lineV;
746             }
747             else
748             {
749                 lineV.push_back(0);
750                 removeDuplicateValueMap[eventNum][strand][copyNumber][base]=lineV;
751             }
752         }
753 
754         // *******************************************
755         // Create the "mergedTableWithoutDuplicatedSB" table
756         // *******************************************
757 
758         // At this point, we have created a map named "removeDuplicateValueMap" that organized all the mergedTable content
759         // AND that does not contain any duplicate because of the override caracteristic of a map.
760         // Indeed, doing map[2] = "hello" followed by map[2]  = "bye" will put map[2] value to "bye" because it overrided the first "hello".
761         // This is a cheap way to remove duplicates by overriding them.
762 
763         // The next part is dedicated to the creation of the "mergedTableWithoutDuplicatedSB" table from the "removeDuplicateValueMap" map.
764         // Only the event, strand and copynumber and  will be put in this final table.
765         Table mergedTableWithoutDuplicatedSB;
766         Table mergedTableWithoutDuplicatedSBandbases;
767         int notDuplicatedLine = 0;
768         int notDuplicatedLine2= 0;
769         // Loop on all the events
770         std::map<ullint,std::map<ullint,std::map<ullint,std::map<ullint,std::vector<ullint>>>>>::iterator 
771             iit = removeDuplicateValueMap.begin();
772         std::map<ullint,std::map<ullint,std::map<ullint,std::map<ullint,std::vector<ullint>>>>>::iterator 
773             iite = removeDuplicateValueMap.end();
774         for(; iit!=iite;++iit)
775         {
776             ullint eventNum = iit->first;
777             // Loop on all the strands
778             std::map<ullint, std::map<ullint, std::map<ullint, std::vector<ullint > > > >::iterator 
779                 itt = iit->second.begin();
780             std::map<ullint, std::map<ullint, std::map<ullint, std::vector<ullint > > > >::iterator 
781                 itte = iit->second.end();
782             for(; itt!=itte;++itt)
783             {
784                 ullint strand = itt->first;
785                 // Loop on all the copy numbers
786                 std::map<ullint, std::map<ullint, std::vector<ullint > > >::iterator ittt = itt->second.begin();
787                 std::map<ullint, std::map<ullint, std::vector<ullint > > >::iterator ittte = itt->second.end();
788                 for(; ittt!=ittte;++ittt)
789                 {
790                     ullint copyNumber = ittt->first;                    
791                 // Loop on all the base flag
792                     std::map<ullint, std::vector<ullint > >::iterator itttt = ittt->second.begin();
793                     std::map<ullint, std::vector<ullint > >::iterator itttte = ittt->second.end();
794                     for(; itttt!=itttte;++itttt)
795                     {
796                         ullint base = itttt->first;
797                         // Fill the table
798                         if (strand>0 && strand<3)
799                         {
800                             // Add a line
801                             mergedTableWithoutDuplicatedSB.push_back(std::vector<ullint>());                           
802                             // Fill the line
803                             mergedTableWithoutDuplicatedSB[notDuplicatedLine].push_back(eventNum);
804                             mergedTableWithoutDuplicatedSB[notDuplicatedLine].push_back(strand);
805                             mergedTableWithoutDuplicatedSB[notDuplicatedLine].push_back(copyNumber);
806                             mergedTableWithoutDuplicatedSB[notDuplicatedLine].push_back(base);
807                             mergedTableWithoutDuplicatedSB[notDuplicatedLine].push_back(
808                                 removeDuplicateValueMap[eventNum][strand][copyNumber][base][0]);
809                             mergedTableWithoutDuplicatedSB[notDuplicatedLine].push_back(
810                                 removeDuplicateValueMap[eventNum][strand][copyNumber][base][1]);
811                             mergedTableWithoutDuplicatedSB[notDuplicatedLine].push_back(
812                                 removeDuplicateValueMap[eventNum][strand][copyNumber][base][2]);
813                             ++notDuplicatedLine;                           
814                             if (base==0)
815                             {
816                                 // Add a line
817                                 mergedTableWithoutDuplicatedSBandbases.push_back(std::vector<ullint>());                              
818                                 // Fill the line
819                                 mergedTableWithoutDuplicatedSBandbases[notDuplicatedLine2].push_back(eventNum);
820                                 mergedTableWithoutDuplicatedSBandbases[notDuplicatedLine2].push_back(strand);
821                                 mergedTableWithoutDuplicatedSBandbases[notDuplicatedLine2].push_back(copyNumber);                               
822                                 ++notDuplicatedLine2;
823                             }
824                         }
825                     }
826                 }
827             }
828         }
829 
830         // *******************************************
831         // Print the "mergedTableWithoutDuplicatedSB" table for the current chromosome
832         // *******************************************
833         if (mergedTableWithoutDuplicatedSB.size() > 0) {
834             //PrintTable(fMergeFolder + "/chromo_"+std::to_string(chromo)+".dat", 
835             //mergedTableWithoutDuplicatedSB, "eventNum, strand, copyNumber, isbase, 
836             //time(ns*1000000), edep, phy:0 chem:1");
837             fMergedTables.insert({chromo,mergedTableWithoutDuplicatedSB});
838         }
839         mergedTable.clear();
840         mergedTableWithoutDuplicatedSBandbases.clear();
841         mergedTableWithoutDuplicatedSB.clear();
842     }
843     //free memory:
844     fphysSlectedTables.clear();
845     fchemSlectedTables.clear();
846 }
847 
848 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
849 
850 void ScanDamage::ReadCellandVoxelDefFilePaths()
851 {
852     fs::path thisP = fs::current_path();
853     for (const auto entry : fs::directory_iterator(thisP)){
854         if (entry.path().filename() == "imp.info") {
855             std::ifstream file(entry.path().c_str());
856             if(!file.good() ){
857                 std::cerr<<"**** Fatal Error *****"<<std::endl;
858                 std::cerr<<"ScanDamage::ReadCellandVoxelDefFilePaths(): File corupted: "
859                 <<entry.path()<<std::endl;
860                 std::cerr<<"*************** *****"<<std::endl;
861                 exit(EXIT_FAILURE);
862             }
863 
864             std::string line;
865             while(std::getline(file, line) ){
866                 std::istringstream iss(line);
867                 std::string flag;
868                 iss >> flag;
869                 if ( flag == "_geovolxelpath") {
870                     std::string voxname;
871                     iss >> voxname;
872                     fVoxelDefFilesList.insert(voxname);
873                 }
874                 if ( flag == "_geocellpath") {
875                     std::string cellpname;
876                     iss >> cellpname;
877                     fCellDefFilePath = cellpname;
878                 }
879                 if ( flag == "_numberOfBasepairs") {
880                     iss >> fTotalNbBpPlacedInGeo;
881                 }
882                 if ( flag == "_numberOfHistones") {
883                     iss >> fTotalNbHistonePlacedInGeo;
884                 }
885                 if ( flag == "_nucleusVolume") {
886                     iss >> fNucleusVolume;
887                 }
888                 if ( flag == "_nucleusMassDensity") {
889                     iss >> fNucleusMassDensity;
890                 }
891                 if ( flag == "_nucleusMass") {
892                     iss >> fNucleusMass;
893                 }
894             }
895             file.close();
896         }
897     }
898 }
899 
900 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....