Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/examples/extended/medical/dna/dnadamage2/src/ScoreSpecies.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 // This example is provided by the Geant4-DNA collaboration
 27 // dnadamage3 example is derived from the chem6 example
 28 // chem6 example authors: W. G. Shin and S. Incerti (CENBG, France)
 29 //
 30 // Any report or published results obtained using the Geant4-DNA software
 31 // shall cite the following Geant4-DNA collaboration publication:
 32 // J. Appl. Phys. 125 (2019) 104301
 33 // Med. Phys. 45 (2018) e722-e739
 34 // J. Comput. Phys. 274 (2014) 841-882
 35 // Med. Phys. 37 (2010) 4692-4708
 36 // Int. J. Model. Simul. Sci. Comput. 1 (2010) 157-178
 37 // The Geant4-DNA web site is available at http://geant4-dna.org
 38 //
 39 // Authors: J. Naoki D. Kondo (UCSF, US)
 40 //          J. Ramos-Mendez and B. Faddegon (UCSF, US)
 41 //
 42 /// \file ScoreSpecies.cc
 43 /// \brief Implementation of the ScoreSpecies class
 44 ///
 45 ///  This is a primitive scorer class for molecular species.
 46 ///  The number of species is recorded for all times (predetermined or
 47 ///  user chosen). It also scores the energy deposition in order to compute the
 48 ///  radiochemical yields.
 49 
 50 #include "ScoreSpecies.hh"
 51 
 52 #include "G4AnalysisManager.hh"
 53 #include "G4Event.hh"
 54 #include "G4Scheduler.hh"
 55 #include "G4TScoreNtupleWriter.hh"
 56 #include "G4UImessenger.hh"
 57 #include "G4UnitsTable.hh"
 58 
 59 #include <G4EventManager.hh>
 60 #include <G4MolecularConfiguration.hh>
 61 #include <G4MoleculeCounter.hh>
 62 #include <G4SystemOfUnits.hh>
 63 #include <globals.hh>
 64 
 65 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
 66 
 67 ScoreSpecies::ScoreSpecies(G4String name, G4int depth)
 68   : G4VPrimitiveScorer(name, depth),
 69     G4UImessenger(),
 70     fOutputType("root"),  // other options: "csv", "hdf5", "xml"
 71     fHCID(-1)
 72 {
 73   fSpeciesdir = new G4UIdirectory("/scorer/species/");
 74   fSpeciesdir->SetGuidance("ScoreSpecies commands");
 75 
 76   fAddTimeToRecordcmd = new G4UIcmdWithADoubleAndUnit("/scorer/species/addTimeToRecord", this);
 77 
 78   fTimeBincmd = new G4UIcmdWithAnInteger("/scorer/species/nOfTimeBins", this);
 79 
 80   fOutputTypeUI = new G4UIcmdWithAString("/scorer/species/OutputFormat", this);
 81   fOutputFileUI = new G4UIcmdWithAString("/scorer/species/OutputFile", this);
 82 
 83   G4MoleculeCounter::Instance()->ResetCounter();
 84 }
 85 
 86 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
 87 
 88 ScoreSpecies::~ScoreSpecies()
 89 {
 90   delete fSpeciesdir;
 91   delete fAddTimeToRecordcmd;
 92   delete fTimeBincmd;
 93   delete fOutputTypeUI;
 94   delete fOutputFileUI;
 95 }
 96 
 97 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
 98 
 99 void ScoreSpecies::SetNewValue(G4UIcommand* command, G4String newValue)
100 {
101   if (command == fAddTimeToRecordcmd) {
102     G4double cmdTime = fAddTimeToRecordcmd->GetNewDoubleValue(newValue);
103     AddTimeToRecord(cmdTime);
104   }
105   if (command == fTimeBincmd) {
106     ClearTimeToRecord();
107     G4int cmdBins = fTimeBincmd->GetNewIntValue(newValue);
108     G4double timeMin = 1 * ps;
109     G4double timeMax = G4Scheduler::Instance()->GetEndTime() - 1 * ps;
110     G4double timeLogMin = std::log10(timeMin);
111     G4double timeLogMax = std::log10(timeMax);
112     for (G4int i = 0; i < cmdBins; i++) {
113       AddTimeToRecord(std::pow(10, timeLogMin + i * (timeLogMax - timeLogMin) / (cmdBins - 1)));
114     }
115   }
116 
117   if (command == fOutputTypeUI) {
118     fOutputType = newValue;
119     G4StrUtil::to_lower(fOutputType);
120   }
121 
122   if (command == fOutputFileUI) fOutputFile = newValue;
123 }
124 
125 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
126 
127 G4bool ScoreSpecies::ProcessHits(G4Step* aStep, G4TouchableHistory*)
128 {
129   G4double edep = aStep->GetTotalEnergyDeposit();
130 
131   if (edep == 0.) return FALSE;
132 
133   edep *= aStep->GetPreStepPoint()->GetWeight();
134   G4int index = GetIndex(aStep);
135   fEvtMap->add(index, edep);
136   fEdep += edep;
137 
138   return TRUE;
139 }
140 
141 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
142 
143 void ScoreSpecies::Initialize(G4HCofThisEvent* HCE)
144 {
145   fEvtMap = new G4THitsMap<G4double>(GetMultiFunctionalDetector()->GetName(), GetName());
146 
147   if (fHCID < 0) {
148     fHCID = GetCollectionID(0);
149   }
150 
151   HCE->AddHitsCollection(fHCID, (G4VHitsCollection*)fEvtMap);
152   G4MoleculeCounter::Instance()->ResetCounter();
153 }
154 
155 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
156 
157 void ScoreSpecies::EndOfEvent(G4HCofThisEvent*)
158 {
159   if (G4EventManager::GetEventManager()->GetConstCurrentEvent()->IsAborted()) {
160     fEdep = 0.;
161     G4MoleculeCounter::Instance()->ResetCounter();
162     return;
163   }
164 
165   auto species = G4MoleculeCounter::Instance()->GetRecordedMolecules();
166 
167   if (species.get() == 0 || species->size() == 0) {
168     G4cout << "No molecule recorded, energy deposited= " << G4BestUnit(fEdep, "Energy") << G4endl;
169     ++fNEvent;
170     fEdep = 0.;
171     G4MoleculeCounter::Instance()->ResetCounter();
172     return;
173   }
174 
175   for (auto molecule : *species) {
176     for (auto time_mol : fTimeToRecord) {
177       double n_mol = G4MoleculeCounter::Instance()->GetNMoleculesAtTime(molecule, time_mol);
178 
179       if (n_mol < 0) {
180         G4cerr << "N molecules not valid < 0 " << G4endl;
181         G4Exception("", "N<0", FatalException, "");
182       }
183 
184       SpeciesInfo& molInfo = fSpeciesInfoPerTime[time_mol][molecule];
185       molInfo.fNumber += n_mol;
186       molInfo.fNumber2 += n_mol * n_mol;
187       double gValue = (n_mol / (fEdep / eV)) * 100.;
188       molInfo.fG += gValue;
189       molInfo.fG2 += gValue * gValue;
190     }
191   }
192 
193   ++fNEvent;
194 
195   fEdep = 0.;
196   G4MoleculeCounter::Instance()->ResetCounter();
197 }
198 
199 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
200 
201 void ScoreSpecies::AbsorbResultsFromWorkerScorer(G4VPrimitiveScorer* workerScorer)
202 {
203   ScoreSpecies* right = dynamic_cast<ScoreSpecies*>(workerScorer);
204 
205   if (right == 0) {
206     return;
207   }
208   if (right == this) {
209     return;
210   }
211 
212   SpeciesMap::iterator it_map1 = right->fSpeciesInfoPerTime.begin();
213   SpeciesMap::iterator end_map1 = right->fSpeciesInfoPerTime.end();
214 
215   for (; it_map1 != end_map1; ++it_map1) {
216     InnerSpeciesMap& map2 = it_map1->second;
217     InnerSpeciesMap::iterator it_map2 = map2.begin();
218     InnerSpeciesMap::iterator end_map2 = map2.end();
219 
220     for (; it_map2 != end_map2; ++it_map2) {
221       SpeciesInfo& molInfo = fSpeciesInfoPerTime[it_map1->first][it_map2->first];
222       molInfo.fNumber += it_map2->second.fNumber;
223       molInfo.fNumber2 += it_map2->second.fNumber2;
224       molInfo.fG += it_map2->second.fG;
225       molInfo.fG2 += it_map2->second.fG2;
226     }
227   }
228   right->fSpeciesInfoPerTime.clear();
229 
230   fNEvent += right->fNEvent;
231   right->fNEvent = 0;
232   right->fEdep = 0.;
233 }
234 
235 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
236 
237 void ScoreSpecies::DrawAll() {}
238 
239 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
240 
241 void ScoreSpecies::PrintAll()
242 {
243   G4cout << " MultiFunctionalDet  " << detector->GetName() << G4endl;
244   G4cout << " PrimitiveScorer " << GetName() << G4endl;
245   G4cout << " Number of events " << fNEvent << G4endl;
246   G4cout << " Number of energy deposition recorded " << fEvtMap->entries() << G4endl;
247 
248   for (auto itr : *fEvtMap->GetMap()) {
249     G4cout << "  copy no.: " << itr.first << "  energy deposit: " << *(itr.second) / GetUnitValue()
250            << " [" << GetUnit() << "]" << G4endl;
251   }
252 }
253 
254 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
255 
256 void ScoreSpecies::OutputAndClear()
257 {
258   if (G4Threading::IsWorkerThread()) return;
259 
260   //---------------------------------------------------------------------------
261   // Save results
262 
263   if (fOutputType != "ascii") {
264     G4AnalysisManager* analysisManager = G4AnalysisManager::Instance();
265     analysisManager->SetDefaultFileType(fOutputType);
266 
267     if (analysisManager) {
268       this->WriteWithAnalysisManager(analysisManager);
269     }
270   }
271   else
272     OutputToASCII();
273 
274   fNEvent = 0;
275   fSpeciesInfoPerTime.clear();
276 }
277 
278 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
279 
280 void ScoreSpecies::WriteWithAnalysisManager(G4VAnalysisManager* analysisManager)
281 {
282   analysisManager->OpenFile(fOutputFile);
283   int fNtupleID = analysisManager->CreateNtuple("species", "species");
284   analysisManager->CreateNtupleIColumn(fNtupleID, "speciesID");
285   analysisManager->CreateNtupleIColumn(fNtupleID, "number");
286   analysisManager->CreateNtupleIColumn(fNtupleID, "nEvent");
287   analysisManager->CreateNtupleSColumn(fNtupleID, "speciesName");
288   analysisManager->CreateNtupleDColumn(fNtupleID, "time");
289   analysisManager->CreateNtupleDColumn(fNtupleID, "sumG");
290   analysisManager->CreateNtupleDColumn(fNtupleID, "sumG2");
291   analysisManager->FinishNtuple(fNtupleID);
292 
293   for (auto it_map1 : fSpeciesInfoPerTime) {
294     InnerSpeciesMap& map2 = it_map1.second;
295 
296     for (auto it_map2 : map2) {
297       double time = it_map1.first;
298       auto species = it_map2.first;
299       const G4String& name = species->GetName();
300       int molID = it_map2.first->GetMoleculeID();
301       int number = it_map2.second.fNumber;
302       double G = it_map2.second.fG;
303       double G2 = it_map2.second.fG2;
304 
305       analysisManager->FillNtupleIColumn(fNtupleID, 0, molID);
306       analysisManager->FillNtupleIColumn(fNtupleID, 1, number);
307       analysisManager->FillNtupleIColumn(fNtupleID, 2, fNEvent);
308       analysisManager->FillNtupleSColumn(fNtupleID, 3, name);
309       analysisManager->FillNtupleDColumn(fNtupleID, 4, time);
310       analysisManager->FillNtupleDColumn(fNtupleID, 5, G);
311       analysisManager->FillNtupleDColumn(fNtupleID, 6, G2);
312       analysisManager->AddNtupleRow(fNtupleID);
313     }
314   }
315 
316   analysisManager->Write();
317   analysisManager->CloseFile();
318   fRunID++;
319 }
320 
321 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
322 
323 void ScoreSpecies::OutputToASCII()
324 {
325   std::ofstream SpeciesOutput;
326   SpeciesOutput.open(fOutputFile + ".txt");
327 
328   std::map<G4String, std::map<G4double, std::vector<G4double>>> mol;
329 
330   for (auto it_map1 : fSpeciesInfoPerTime) {
331     InnerSpeciesMap& map2 = it_map1.second;
332     G4double time = it_map1.first / ps;
333 
334     for (auto it_map2 : map2) {
335       G4double G = it_map2.second.fG;
336       G4double G2 = it_map2.second.fG2;
337       G4double Nb = it_map2.second.fNumber;
338       G4double Nb2 = it_map2.second.fNumber2;
339       G4double N = fNEvent;
340       if (N > 0) {
341         G /= N;
342         Nb /= N;
343       }
344 
345       if (N == 1) {
346         G2 = 0.0;
347         Nb2 = 0.0;
348       }
349 
350       else if (N > 0) {
351         G2 = std::sqrt(N / (N - 1) * (G2 / N - G * G));
352         Nb2 = std::sqrt(N / (N - 1) * (Nb2 / N - Nb * Nb));
353       }
354 
355       mol[it_map2.first->GetName()][time].push_back(G);
356       mol[it_map2.first->GetName()][time].push_back(G2);
357       mol[it_map2.first->GetName()][time].push_back(Nb);
358       mol[it_map2.first->GetName()][time].push_back(Nb2);
359     }
360   }
361 
362   SpeciesOutput << "# Species Scorer Output " << G4endl;
363   SpeciesOutput << "# " << std::setw(10) << "Time [ps]" << std::setw(15) << "Gx(/100 eV)"
364                 << std::setw(15) << "RMS" << std::setw(15) << "Gx(#Mols)" << std::setw(20)
365                 << "Molecule" << G4endl;
366 
367   for (auto it1 : mol)
368     for (auto it2 : it1.second)
369       SpeciesOutput << std::setw(12) << it2.first << "   " << std::setw(12) << it2.second[0]
370                     << "   " << std::setw(12) << it2.second[1] << "   " << std::setw(12)
371                     << it2.second[2] << "   " << std::setw(17) << it1.first << G4endl;
372 
373   SpeciesOutput.close();
374 }
375 
376 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
377