Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-03-31 07:49:58

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 HistoManager.cc
0027 /// \brief Implementation of the HistoManager class
0028 
0029 //---------------------------------------------------------------------------
0030 //
0031 // ClassName:   HistoManager
0032 //
0033 //
0034 // Author:      V.Ivanchenko 30/01/01
0035 //
0036 //----------------------------------------------------------------------------
0037 //
0038 
0039 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
0040 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
0041 
0042 #include "HistoManager.hh"
0043 
0044 #include "EmAcceptance.hh"
0045 #include "Histo.hh"
0046 
0047 #include "G4Electron.hh"
0048 #include "G4EmProcessSubType.hh"
0049 #include "G4Gamma.hh"
0050 #include "G4GammaGeneralProcess.hh"
0051 #include "G4MaterialCutsCouple.hh"
0052 #include "G4Positron.hh"
0053 #include "G4SystemOfUnits.hh"
0054 #include "G4UnitsTable.hh"
0055 #include "G4VEmProcess.hh"
0056 #include "G4VEnergyLossProcess.hh"
0057 #include "G4VProcess.hh"
0058 
0059 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
0060 
0061 HistoManager* HistoManager::fManager = nullptr;
0062 
0063 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
0064 
0065 HistoManager* HistoManager::GetPointer()
0066 {
0067   if (nullptr == fManager) {
0068     fManager = new HistoManager();
0069   }
0070   return fManager;
0071 }
0072 
0073 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
0074 
0075 HistoManager::HistoManager()
0076   : fGamma(G4Gamma::Gamma()),
0077     fElectron(G4Electron::Electron()),
0078     fPositron(G4Positron::Positron()),
0079     fHisto(new Histo())
0080 {
0081   fVerbose = 1;
0082   fEvt1 = -1;
0083   fEvt2 = -1;
0084   fNmax = 3;
0085   fMaxEnergy = 50.0 * MeV;
0086   fBeamEnergy = 1. * GeV;
0087   fMaxEnergyAbs = 10. * MeV;
0088   fBinsE = 100;
0089   fBinsEA = 40;
0090   fBinsED = 100;
0091   fNHisto = 13;
0092 
0093   BookHisto();
0094 }
0095 
0096 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
0097 
0098 HistoManager::~HistoManager()
0099 {
0100   delete fHisto;
0101 }
0102 
0103 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
0104 
0105 void HistoManager::BookHisto()
0106 {
0107   fHisto->Add1D("10", "Evis/E0 in central crystal", fBinsED, 0.0, 1, 1.0);
0108   fHisto->Add1D("11", "Evis/E0 in 3x3", fBinsED, 0.0, 1.0, 1.0);
0109   fHisto->Add1D("12", "Evis/E0 in 5x5", fBinsED, 0.0, 1.0, 1.0);
0110   fHisto->Add1D("13", "Energy (MeV) of delta-electrons", fBinsE, 0.0, fMaxEnergy, MeV);
0111   fHisto->Add1D("14", "Energy (MeV) of gammas", fBinsE, 0.0, fMaxEnergy, MeV);
0112   fHisto->Add1D("15", "Energy (MeV) in abs1", fBinsEA, 0.0, fMaxEnergyAbs, MeV);
0113   fHisto->Add1D("16", "Energy (MeV) in abs2", fBinsEA, 0.0, fMaxEnergyAbs, MeV);
0114   fHisto->Add1D("17", "Energy (MeV) in abs3", fBinsEA, 0.0, fMaxEnergyAbs, MeV);
0115   fHisto->Add1D("18", "Energy (MeV) in abs4", fBinsEA, 0.0, fMaxEnergyAbs, MeV);
0116   fHisto->Add1D("19", "Number of vertex hits", 20, -0.5, 19.5, 1.0);
0117   fHisto->Add1D("20", "E1/E9 Ratio", fBinsED, 0.0, 1, 1.0);
0118   fHisto->Add1D("21", "E1/E25 Ratio", fBinsED, 0.0, 1.0, 1.0);
0119   fHisto->Add1D("22", "E9/E25 Ratio", fBinsED, 0.0, 1.0, 1.0);
0120 }
0121 
0122 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
0123 
0124 void HistoManager::BeginOfRun()
0125 {
0126   // initilise scoring
0127   fEvt = 0;
0128   fElec = 0;
0129   fPosit = 0;
0130   fGam = 0;
0131   fStep = 0;
0132   fLowe = 0;
0133 
0134   for (G4int i = 0; i < 6; i++) {
0135     fStat[i] = 0;
0136     fEdep[i] = 0.0;
0137     fErms[i] = 0.0;
0138     if (i < 3) {
0139       fEdeptr[i] = 0.0;
0140       fErmstr[i] = 0.0;
0141     }
0142   }
0143 
0144   // initialise counters
0145   fBrem.resize(93, 0.0);
0146   fPhot.resize(93, 0.0);
0147   fComp.resize(93, 0.0);
0148   fConv.resize(93, 0.0);
0149 
0150   // initialise acceptance - by default is not applied
0151   for (G4int i = 0; i < fNmax; i++) {
0152     fEdeptrue[i] = 1.0;
0153     fRmstrue[i] = 1.0;
0154     fLimittrue[i] = 10.;
0155   }
0156 
0157   if (fHisto->IsActive()) {
0158     for (G4int i = 0; i < fNHisto; ++i) {
0159       fHisto->Activate(i, true);
0160     }
0161     fHisto->Book();
0162 
0163     if (fVerbose > 0) {
0164       G4cout << "HistoManager: Histograms are booked and run has been started" << G4endl;
0165     }
0166   }
0167 }
0168 
0169 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
0170 
0171 void HistoManager::EndOfRun(G4int runID)
0172 {
0173   G4cout << "HistoManager: End of run actions are started   RunID# " << runID << G4endl;
0174   G4String nam[6] = {"1x1", "3x3", "5x5", "E1/E9 ", "E1/E25", "E9/E25"};
0175 
0176   // average
0177 
0178   G4cout << "=================================================================" << G4endl;
0179   G4double x = (G4double)fEvt;
0180   if (fEvt > 0) x = 1.0 / x;
0181   G4int j;
0182   for (j = 0; j < fNmax; j++) {
0183     // total mean
0184     fEdep[j] *= x;
0185     G4double y = fErms[j] * x - fEdep[j] * fEdep[j];
0186     if (y < 0.0) y = 0.0;
0187     fErms[j] = std::sqrt(y);
0188 
0189     // trancated mean
0190     G4double xx = G4double(fStat[j]);
0191     if (xx > 0.0) xx = 1.0 / xx;
0192     fEdeptr[j] *= xx;
0193     y = fErmstr[j] * xx - fEdeptr[j] * fEdeptr[j];
0194     if (y < 0.0) y = 0.0;
0195     fErmstr[j] = std::sqrt(y);
0196   }
0197   G4double xe = x * (G4double)fElec;
0198   G4double xg = x * (G4double)fGam;
0199   G4double xp = x * (G4double)fPosit;
0200   G4double xs = x * fStep;
0201 
0202   G4double f = 100. * std::sqrt(fBeamEnergy / GeV);
0203 
0204   G4cout << "Number of events             " << fEvt << G4endl;
0205   G4cout << std::setprecision(4) << "Average number of e-         " << xe << G4endl;
0206   G4cout << std::setprecision(4) << "Average number of gamma      " << xg << G4endl;
0207   G4cout << std::setprecision(4) << "Average number of e+         " << xp << G4endl;
0208   G4cout << std::setprecision(4) << "Average number of steps      " << xs << G4endl;
0209 
0210   for (j = 0; j < 3; ++j) {
0211     G4double ex = fEdeptr[j];
0212     G4double sx = fErmstr[j];
0213     G4double xx = G4double(fStat[j]);
0214     if (xx > 0.0) xx = 1.0 / xx;
0215     G4double r = sx * std::sqrt(xx);
0216     G4cout << std::setprecision(4) << "Edep " << nam[j] << " =                   " << ex << " +- "
0217            << r;
0218     if (ex > 0.1) G4cout << "  res=  " << f * sx / ex << " %   " << fStat[j];
0219     G4cout << G4endl;
0220   }
0221   if (fLimittrue[0] < 10. || fLimittrue[1] < 10. || fLimittrue[2] < 10.) {
0222     G4cout << "===========  Mean values without trancating =====================" << G4endl;
0223     for (j = 0; j < fNmax; j++) {
0224       G4double ex = fEdep[j];
0225       G4double sx = fErms[j];
0226       G4double rx = sx * std::sqrt(x);
0227       G4cout << std::setprecision(4) << "Edep " << nam[j] << " =                   " << ex << " +- "
0228              << rx;
0229       if (ex > 0.0) G4cout << "  res=  " << f * sx / ex << " %";
0230       G4cout << G4endl;
0231     }
0232   }
0233   G4cout << "===========  Ratios without trancating ===========================" << G4endl;
0234   for (j = 3; j < 6; ++j) {
0235     G4double e = fEdep[j];
0236     G4double xx = G4double(fStat[j]);
0237     if (xx > 0.0) xx = 1.0 / xx;
0238     e *= xx;
0239     G4double y = fErms[j] * xx - e * e;
0240     G4double r = 0.0;
0241     if (y > 0.0) r = std::sqrt(y * xx);
0242     G4cout << "  " << nam[j] << " =                   " << e << " +- " << r;
0243     G4cout << G4endl;
0244   }
0245   G4cout << std::setprecision(4) << "Beam Energy                  " << fBeamEnergy / GeV << " GeV"
0246          << G4endl;
0247   if (fLowe > 0) G4cout << "Number of events E/E0<0.8    " << fLowe << G4endl;
0248   G4cout << "==================================================================" << G4endl;
0249   G4cout << G4endl;
0250 
0251   // normalise histograms
0252   if (fHisto->IsActive()) {
0253     for (G4int i = 0; i < fNHisto; ++i) {
0254       fHisto->ScaleH1(i, x);
0255     }
0256     fHisto->Save();
0257   }
0258   if (0 < runID) {
0259     return;
0260   }
0261 
0262   // Acceptance only for the first run
0263   EmAcceptance acc;
0264   G4bool isStarted = false;
0265   for (j = 0; j < fNmax; j++) {
0266     G4double ltrue = fLimittrue[j];
0267     if (ltrue < DBL_MAX) {
0268       if (!isStarted) {
0269         acc.BeginOfAcceptance("Crystal Calorimeter", fEvt);
0270         isStarted = true;
0271       }
0272       G4double etrue = fEdeptrue[j];
0273       G4double rtrue = fRmstrue[j];
0274       acc.EmAcceptanceGauss("Edep" + nam[j], fEvt, fEdeptr[j], etrue, rtrue, ltrue);
0275       acc.EmAcceptanceGauss("Erms" + nam[j], fEvt, fErmstr[j], rtrue, rtrue, 2.0 * ltrue);
0276     }
0277   }
0278   if (isStarted) acc.EndOfAcceptance();
0279 
0280   // atom frequency
0281   G4cout << "   Z  bremsstrahlung photoeffect  compton    conversion" << G4endl;
0282   for (j = 1; j < 93; ++j) {
0283     G4int n1 = G4int(fBrem[j] * x);
0284     G4int n2 = G4int(fPhot[j] * x);
0285     G4int n3 = G4int(fComp[j] * x);
0286     G4int n4 = G4int(fConv[j] * x);
0287     if (n1 + n2 + n3 + n4 > 0) {
0288       G4cout << std::setw(4) << j << std::setw(12) << n1 << std::setw(12) << n2 << std::setw(12)
0289              << n3 << std::setw(12) << n4 << G4endl;
0290     }
0291   }
0292 }
0293 
0294 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
0295 
0296 void HistoManager::BeginOfEvent()
0297 {
0298   ++fEvt;
0299 
0300   fEabs1 = 0.0;
0301   fEabs2 = 0.0;
0302   fEabs3 = 0.0;
0303   fEabs4 = 0.0;
0304   fEvertex.clear();
0305   fNvertex.clear();
0306   for (G4int i = 0; i < 25; i++) {
0307     fE[i] = 0.0;
0308   }
0309 }
0310 
0311 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
0312 
0313 void HistoManager::EndOfEvent()
0314 {
0315   G4double e9 = 0.0;
0316   G4double e25 = 0.0;
0317   for (G4int i = 0; i < 25; i++) {
0318     fE[i] /= fBeamEnergy;
0319     e25 += fE[i];
0320     if ((6 <= i && 8 >= i) || (11 <= i && 13 >= i) || (16 <= i && 18 >= i)) e9 += fE[i];
0321   }
0322 
0323   if (1 < fVerbose && e25 < 0.8) {
0324     ++fLowe;
0325     G4cout << "### in the event# " << fEvt << "  E25= " << e25 << G4endl;
0326   }
0327 
0328   // compute ratios
0329   G4double e0 = fE[12];
0330   G4double e19 = 0.0;
0331   G4double e125 = 0.0;
0332   G4double e925 = 0.0;
0333   if (e9 > 0.0) {
0334     e19 = e0 / e9;
0335     e125 = e0 / e25;
0336     e925 = e9 / e25;
0337     fEdep[3] += e19;
0338     fErms[3] += e19 * e19;
0339     fEdep[4] += e125;
0340     fErms[4] += e125 * e125;
0341     fEdep[5] += e925;
0342     fErms[5] += e925 * e925;
0343     fStat[3] += 1;
0344     fStat[4] += 1;
0345     fStat[5] += 1;
0346   }
0347 
0348   // Fill histo
0349   fHisto->Fill(0, e0, 1.0);
0350   fHisto->Fill(1, e9, 1.0);
0351   fHisto->Fill(2, e25, 1.0);
0352   fHisto->Fill(5, fEabs1, 1.0);
0353   fHisto->Fill(6, fEabs2, 1.0);
0354   fHisto->Fill(7, fEabs3, 1.0);
0355   fHisto->Fill(8, fEabs4, 1.0);
0356   fHisto->Fill(9, G4double(fNvertex.size()), 1.0);
0357   fHisto->Fill(10, e19, 1.0);
0358   fHisto->Fill(11, e125, 1.0);
0359   fHisto->Fill(12, e925, 1.0);
0360 
0361   // compute sums
0362   fEdep[0] += e0;
0363   fErms[0] += e0 * e0;
0364   fEdep[1] += e9;
0365   fErms[1] += e9 * e9;
0366   fEdep[2] += e25;
0367   fErms[2] += e25 * e25;
0368 
0369   // trancated mean
0370   if (std::abs(e0 - fEdeptrue[0]) < fRmstrue[0] * fLimittrue[0]) {
0371     fStat[0] += 1;
0372     fEdeptr[0] += e0;
0373     fErmstr[0] += e0 * e0;
0374   }
0375   if (std::abs(e9 - fEdeptrue[1]) < fRmstrue[1] * fLimittrue[1]) {
0376     fStat[1] += 1;
0377     fEdeptr[1] += e9;
0378     fErmstr[1] += e9 * e9;
0379   }
0380   if (std::abs(e25 - fEdeptrue[2]) < fRmstrue[2] * fLimittrue[2]) {
0381     fStat[2] += 1;
0382     fEdeptr[2] += e25;
0383     fErmstr[2] += e25 * e25;
0384   }
0385 }
0386 
0387 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
0388 
0389 void HistoManager::ScoreNewTrack(const G4Track* aTrack)
0390 {
0391   // Save primary parameters
0392   ResetTrackLength();
0393   const G4ParticleDefinition* particle = aTrack->GetDefinition();
0394   const G4DynamicParticle* dynParticle = aTrack->GetDynamicParticle();
0395 
0396   G4int pid = aTrack->GetParentID();
0397   G4double kinE = dynParticle->GetKineticEnergy();
0398   G4ThreeVector pos = aTrack->GetVertexPosition();
0399 
0400   // primary
0401   if (0 == pid) {
0402     G4double mass = 0.0;
0403     if (particle) {
0404       mass = particle->GetPDGMass();
0405     }
0406 
0407     G4ThreeVector dir = dynParticle->GetMomentumDirection();
0408     if (1 < fVerbose) {
0409       G4cout << "TrackingAction: Primary kinE(MeV)= " << kinE / MeV << "; m(MeV)= " << mass / MeV
0410              << "; pos= " << pos << ";  dir= " << dir << G4endl;
0411     }
0412 
0413     // secondary
0414   }
0415   else {
0416     const G4VProcess* proc = aTrack->GetCreatorProcess();
0417     G4int type = proc->GetProcessSubType();
0418 
0419     if (type == fBremsstrahlung) {
0420       auto elm = static_cast<const G4VEnergyLossProcess*>(proc)->GetCurrentElement();
0421       if (nullptr != elm) {
0422         G4int Z = elm->GetZasInt();
0423         if (Z > 0 && Z < 93) {
0424           fBrem[Z] += 1.0;
0425         }
0426       }
0427     }
0428     else if (type == fPhotoElectricEffect) {
0429       auto elm = static_cast<const G4VEmProcess*>(proc)->GetCurrentElement();
0430       if (nullptr != elm) {
0431         G4int Z = elm->GetZasInt();
0432         if (Z > 0 && Z < 93) {
0433           fPhot[Z] += 1.0;
0434         }
0435       }
0436     }
0437     else if (type == fGammaConversion) {
0438       auto elm = static_cast<const G4VEmProcess*>(proc)->GetCurrentElement();
0439       if (nullptr != elm) {
0440         G4int Z = elm->GetZasInt();
0441         if (Z > 0 && Z < 93) {
0442           fConv[Z] += 1.0;
0443         }
0444       }
0445     }
0446     else if (type == fComptonScattering) {
0447       auto elm = static_cast<const G4VEmProcess*>(proc)->GetCurrentElement();
0448       if (nullptr != elm) {
0449         G4int Z = elm->GetZasInt();
0450         if (Z > 0 && Z < 93) {
0451           fComp[Z] += 1.0;
0452         }
0453       }
0454     }
0455 
0456     // delta-electron
0457     if (particle == fElectron) {
0458       if (1 < fVerbose) {
0459         G4cout << "TrackingAction: Secondary electron " << G4endl;
0460       }
0461       AddDeltaElectron(dynParticle);
0462     }
0463     else if (particle == fPositron) {
0464       if (1 < fVerbose) {
0465         G4cout << "TrackingAction: Secondary positron " << G4endl;
0466       }
0467       AddPositron(dynParticle);
0468     }
0469     else if (particle == fGamma) {
0470       if (1 < fVerbose) {
0471         G4cout << "TrackingAction: Secondary gamma; parentID= " << pid << " E= " << kinE << G4endl;
0472       }
0473       AddPhoton(dynParticle);
0474     }
0475   }
0476 }
0477 
0478 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0479 
0480 void HistoManager::AddEnergy(G4double edep, G4int volIndex, G4int copyNo)
0481 {
0482   if (1 < fVerbose) {
0483     G4cout << "HistoManager::AddEnergy: e(keV)= " << edep / keV << "; volIdx= " << volIndex
0484            << "; copyNo= " << copyNo << G4endl;
0485   }
0486   if (0 == volIndex) {
0487     fE[copyNo] += edep;
0488   }
0489   else if (1 == volIndex) {
0490     fEabs1 += edep;
0491   }
0492   else if (2 == volIndex) {
0493     fEabs2 += edep;
0494   }
0495   else if (3 == volIndex) {
0496     fEabs3 += edep;
0497   }
0498   else if (4 == volIndex) {
0499     fEabs4 += edep;
0500   }
0501   else if (5 == volIndex) {
0502     G4int n = fNvertex.size();
0503     G4bool newPad = true;
0504     if (n > 0) {
0505       for (G4int i = 0; i < n; i++) {
0506         if (copyNo == fNvertex[i]) {
0507           newPad = false;
0508           fEvertex[i] += edep;
0509           break;
0510         }
0511       }
0512     }
0513     if (newPad) {
0514       fNvertex.push_back(copyNo);
0515       fEvertex.push_back(edep);
0516     }
0517   }
0518 }
0519 
0520 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
0521 
0522 void HistoManager::AddDeltaElectron(const G4DynamicParticle* elec)
0523 {
0524   G4double e = elec->GetKineticEnergy() / MeV;
0525   if (e > 0.0) {
0526     ++fElec;
0527     fHisto->Fill(3, e, 1.0);
0528   }
0529 }
0530 
0531 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
0532 
0533 void HistoManager::AddPhoton(const G4DynamicParticle* ph)
0534 {
0535   G4double e = ph->GetKineticEnergy() / MeV;
0536   if (e > 0.0) {
0537     ++fGam;
0538     fHisto->Fill(4, e, 1.0);
0539   }
0540 }
0541 
0542 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
0543 
0544 void HistoManager::SetEdepAndRMS(G4int i, const G4ThreeVector& val)
0545 {
0546   if (i < fNmax && i >= 0) {
0547     if (val[0] > 0.0) fEdeptrue[i] = val[0];
0548     if (val[1] > 0.0) fRmstrue[i] = val[1];
0549     if (val[2] > 0.0) fLimittrue[i] = val[2];
0550   }
0551 }
0552 
0553 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....