BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSOutput.cc
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) BDSIM Collaboration, 2001 - 2026.
3
4This file is part of BDSIM.
5
6BDSIM is free software: you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published
8by the Free Software Foundation version 3 of the License.
9
10BDSIM is distributed in the hope that it will be useful, but
11WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with BDSIM. If not, see <http://www.gnu.org/licenses/>.
17*/
18#include "BDSAcceleratorModel.hh"
19#include "BDSBeamline.hh"
20#include "BDSBeamlineElement.hh"
21#include "BDSBLMRegistry.hh"
22#include "BDSDebug.hh"
23#include "BDSEventInfo.hh"
24#include "BDSException.hh"
25#include "BDSGlobalConstants.hh"
26#include "BDSHistBinMapper.hh"
27#include "BDSHitApertureImpact.hh"
28#include "BDSHitCollimator.hh"
29#include "BDSHitEnergyDeposition.hh"
30#include "BDSHitEnergyDepositionGlobal.hh"
31#include "BDSHitSampler.hh"
32#include "BDSHitSamplerCylinder.hh"
33#include "BDSHitSamplerSphere.hh"
34#include "BDSHitSamplerLink.hh"
35#include "BDSOutput.hh"
36#include "BDSOutputROOTEventAperture.hh"
37#include "BDSOutputROOTEventBeam.hh"
38#include "BDSOutputROOTEventCollimator.hh"
39#include "BDSOutputROOTEventCavityInfo.hh"
40#include "BDSOutputROOTEventCollimatorInfo.hh"
41#include "BDSOutputROOTEventCoords.hh"
42#include "BDSOutputROOTEventLossWorld.hh"
43#include "BDSOutputROOTEventHeader.hh"
44#include "BDSOutputROOTEventHistograms.hh"
45#include "BDSOutputROOTEventInfo.hh"
46#include "BDSOutputROOTEventLoss.hh"
47#include "BDSOutputROOTEventModel.hh"
48#include "BDSOutputROOTEventOptions.hh"
49#include "BDSOutputROOTEventRunInfo.hh"
50#include "BDSOutputROOTEventSampler.hh"
51#include "BDSOutputROOTEventSamplerC.hh"
52#include "BDSOutputROOTEventSamplerS.hh"
53#include "BDSOutputROOTEventTrajectory.hh"
54#include "BDSOutputROOTParticleData.hh"
55#include "BDSParticleDefinition.hh"
56#include "BDSPrimaryVertexInformation.hh"
57#include "BDSPrimaryVertexInformationV.hh"
58#include "BDSScorerHistogramDef.hh"
59#include "BDSSDManager.hh"
60#include "BDSStackingAction.hh"
61#include "BDSTrajectoriesToStore.hh"
62#include "BDSTrajectoryPoint.hh"
63#include "BDSTrajectoryPointHit.hh"
64#include "BDSUtilities.hh"
65
66#include "globals.hh"
67#include "G4ParticleDefinition.hh"
68#include "G4PrimaryParticle.hh"
69#include "G4PrimaryVertex.hh"
70#include "G4THitsMap.hh"
71#include "G4Version.hh"
72
73#include "TH1D.h"
74#include "TH3D.h"
75
76#include "parser/beamBase.h"
77#include "parser/optionsBase.h"
78
79#include <algorithm>
80#include <cmath>
81#include <map>
82#include <ostream>
83#include <set>
84#include <utility>
85#include <vector>
86
87#include "CLHEP/Units/SystemOfUnits.h"
88
89const std::set<G4String> BDSOutput::protectedNames = {
90 "Event", "Histos", "Info", "Primary", "PrimaryGlobal",
91 "Eloss", "ElossVacuum", "ElossTunnel", "ElossWorld", "ElossWorldExit",
92 "ElossWorldContents",
93 "PrimaryFirstHit", "PrimaryLastHit", "Trajectory", "ApertureImpacts"
94};
95
96BDSOutput::BDSOutput(const G4String& baseFileNameIn,
97 const G4String& fileExtensionIn,
98 G4int fileNumberOffset):
100 baseFileName(baseFileNameIn),
101 fileExtension(fileExtensionIn),
102 outputFileNumber(fileNumberOffset),
103 sMinHistograms(0),
104 sMaxHistograms(0),
105 nbins(0),
106 energyDeposited(0),
107 energyDepositedVacuum(0),
108 energyDepositedWorld(0),
109 energyDepositedWorldContents(0),
110 energyDepositedTunnel(0),
111 energyImpactingAperture(0),
112 energyImpactingApertureKinetic(0),
113 energyWorldExit(0),
114 energyWorldExitKinetic(0),
115 nCollimatorsInteracted(0)
116{
118 numberEventPerFile = g->NumberOfEventsPerNtuple();
119 useScoringMap = g->UseScoringMap();
120
121 sMinHistograms = g->BeamlineS();
122 storeApertureImpacts = g->StoreApertureImpacts();
123 storeApertureImpactsHistograms = g->StoreApertureImpactsHistograms();
124 storeCavityInfo = g->StoreCavityInfo();
125 storeCollimatorInfo = g->StoreCollimatorInfo();
126 storeCollimatorHitsLinks = g->StoreCollimatorHitsLinks();
127 storeCollimatorHitsIons = g->StoreCollimatorHitsIons();
128 // store primary hits if ion hits or links hits are turned on
129 storeCollimatorHits = g->StoreCollimatorHits() || storeCollimatorHitsLinks || storeCollimatorHitsIons || g->StoreCollimatorHitsAll();
130
132
133 storeELoss = g->StoreELoss();
134 // store histograms if storing general energy deposition as negligible in size
135 storeELossHistograms = g->StoreELossHistograms() || storeELoss;
136 storeELossTunnel = g->StoreELossTunnel();
137 storeELossTunnelHistograms = g->StoreELossTunnelHistograms() || storeELossTunnel;
138 storeELossVacuum = g->StoreELossVacuum();
139 storeELossVacuumHistograms = g->StoreELossVacuumHistograms() || storeELossVacuum;
140 storeELossWorld = g->StoreELossWorld();
141 storeELossWorldContents = g->StoreELossWorldContents() || g->UseImportanceSampling();
142 storeParticleData = g->StoreParticleData();
143 storeModel = g->StoreModel();
144 storePrimaries = g->StorePrimaries();
145 storePrimaryHistograms = g->StorePrimaryHistograms();
146 storeSamplerPolarCoords = g->StoreSamplerPolarCoords();
147 storeSamplerCharge = g->StoreSamplerCharge();
148 storeSamplerKineticEnergy = g->StoreSamplerKineticEnergy();
149 storeSamplerMass = g->StoreSamplerMass();
150 storeSamplerRigidity = g->StoreSamplerRigidity();
151 storeSamplerIon = g->StoreSamplerIon();
152 storeTrajectory = g->StoreTrajectory();
153 storeTrajectoryStepPoints = g->StoreTrajectoryStepPoints();
154 storeTrajectoryStepPointLast = g->StoreTrajectoryStepPointLast();
156 storePerEventHistos = g->StorePerEventHistos();
157
158 // easy option for everything - overwrite bools we've just set individually
159 if (g->StoreSamplerAll())
160 {
162 storeSamplerCharge = true;
164 storeSamplerMass = true;
166 storeSamplerIon = true;
167 }
168}
169
171{
173 {
174 PrepareCollimatorInformation(); // prepare names, offsets and indices
175 InitialiseCollimators(); // allocate local objects
176 }
177 if (storeCavityInfo)
178 {PrepareCavityInformation();} // prepare names, offsets and indices
182}
183
185{
186 headerOutput->Flush();
187 headerOutput->Fill(); // updates time stamp
188 WriteHeader();
189 // we purposively don't call ClearStructuresHeader() as we may yet update and overwrite the header info
190}
191
192void BDSOutput::FillParticleData(G4bool writeIons)
193{
194 // always prepare particle data and link to other classes, but optionally fill it
196 particleDataOutput->Fill(writeIons);
197
198#ifdef __ROOTDOUBLE__
200#else
202#endif
203 BDSOutputROOTEventCollimator::particleTable = particleDataOutput;
204 BDSOutputROOTEventAperture::particleTable = particleDataOutput;
205
208}
209
216
223
225{
226 if (storeModel)
227 {
228 const auto& smpm = BDSAcceleratorModel::Instance()->ScorerMeshPlacementsMap();
237 &smpm,
238 &materialIDToNameUnique,
240 WriteModel();
242 }
243}
244
245void BDSOutput::FillPrimary(const G4PrimaryVertex* vertex,
246 const G4int turnsTaken)
247{
248 const G4VUserPrimaryVertexInformation* vertexInfo = vertex->GetUserInformation();
249 if (const auto vertexInfoBDS = dynamic_cast<const BDSPrimaryVertexInformation*>(vertexInfo))
250 {
251 primary->Fill(vertexInfoBDS->primaryVertex.local,
252 vertexInfoBDS->momentum,
253 vertexInfoBDS->charge,
254 vertexInfoBDS->pdgID,
255 turnsTaken,
256 vertexInfoBDS->primaryVertex.beamlineIndex,
257 vertexInfoBDS->nElectrons,
258 vertexInfoBDS->mass,
259 vertexInfoBDS->rigidity);
260 primaryGlobal->Fill(vertexInfoBDS->primaryVertex.global);
261 }
262 else if (const auto vertexInfoBDSV = dynamic_cast<const BDSPrimaryVertexInformationV*>(vertexInfo))
263 {// vector version - multiple primaries at primary vertex
264 primary->Fill(vertexInfoBDSV, turnsTaken);
265 primaryGlobal->Fill(vertexInfoBDSV);
266 }
267 auto nextLinkedVertex = vertex->GetNext();
268 if (nextLinkedVertex)
269 {FillPrimary(nextLinkedVertex, turnsTaken);}
270}
271
273 const BDSParticleDefinition* particle)
274{
275 G4bool isIon = particle->IsAnIon();
276 G4int ionA = 0;
277 G4int ionZ = 0;
278 if (isIon)
279 {// fill primary ion info correctly when we have no particle table available
280 ionA = particle->IonDefinition()->A();
281 ionZ = particle->IonDefinition()->Z();
282 }
283 primary->Fill(coords.local,
284 particle->Momentum(),
285 particle->Charge(),
286 particle->PDGID(),
287 0, 0,
288 particle->NElectrons(),
289 particle->Mass(),
290 particle->BRho(),
291 true,
292 &isIon, &ionA, &ionZ);
293 primaryGlobal->Fill(coords.global);
296}
297
299 const G4PrimaryVertex* vertex,
300 const std::vector<BDSHitsCollectionSampler*>& samplerHitsPlane,
301 const std::vector<BDSHitsCollectionSamplerCylinder*>& samplerHitsCylinder,
302 const std::vector<BDSHitsCollectionSamplerSphere*>& samplerHitsSphere,
303 const BDSHitsCollectionSamplerLink* samplerHitsLink,
304 const BDSHitsCollectionEnergyDeposition* energyLoss,
305 const BDSHitsCollectionEnergyDeposition* energyLossFull,
306 const BDSHitsCollectionEnergyDeposition* energyLossVacuum,
307 const BDSHitsCollectionEnergyDeposition* energyLossTunnel,
308 const BDSHitsCollectionEnergyDepositionGlobal* energyLossWorld,
309 const BDSHitsCollectionEnergyDepositionGlobal* energyLossWorldContents,
310 const BDSHitsCollectionEnergyDepositionGlobal* worldExitHits,
311 const std::vector<const BDSTrajectoryPointHit*>& primaryHits,
312 const std::vector<const BDSTrajectoryPointHit*>& primaryLosses,
313 const BDSTrajectoriesToStore* trajectories,
314 const BDSHitsCollectionCollimator* collimatorHits,
315 const BDSHitsCollectionApertureImpacts* apertureImpactHits,
316 const std::map<G4String, G4THitsMap<G4double>*>& scorerHits,
317 const G4int turnsTaken)
318{
319 // Clear integrals in this class -> here instead of BDSOutputStructures as
320 // looped over here -> do only once as expensive as lots of hits
321 energyDeposited = 0;
328 energyWorldExit = 0;
331
332 if (vertex && storePrimaries)
333 {FillPrimary(vertex, turnsTaken);}
334 FillSamplerHitsVector(samplerHitsPlane);
335 FillSamplerCylinderHitsVector(samplerHitsCylinder);
336 FillSamplerSphereHitsVector(samplerHitsSphere);
337 if (samplerHitsLink)
338 {FillSamplerHitsLink(samplerHitsLink);}
339 if (energyLoss)
340 {FillEnergyLoss(energyLoss, BDSOutput::LossType::energy);}
341 if (energyLossFull)
342 {FillEnergyLoss(energyLossFull, BDSOutput::LossType::energy);}
343 if (energyLossVacuum)
344 {FillEnergyLoss(energyLossVacuum, BDSOutput::LossType::vacuum);}
345 if (energyLossTunnel)
346 {FillEnergyLoss(energyLossTunnel, BDSOutput::LossType::tunnel);}
347 if (energyLossWorld)
348 {FillEnergyLoss(energyLossWorld, BDSOutput::LossType::world);}
349 if (worldExitHits)
350 {FillEnergyLoss(worldExitHits, BDSOutput::LossType::worldexit);}
351 if (energyLossWorldContents)
352 {FillEnergyLoss(energyLossWorldContents, BDSOutput::LossType::worldcontents);}
353 FillPrimaryHit(primaryHits);
354 FillPrimaryLoss(primaryLosses);
355 if (trajectories)
356 {FillTrajectories(trajectories);}
357 if (collimatorHits)
358 {FillCollimatorHits(collimatorHits, primaryLosses);}
359 if (apertureImpacts)
360 {FillApertureImpacts(apertureImpactHits);}
361 FillScorerHits(scorerHits); // map always exists
362
363 // we do this after energy loss and collimator hits as the energy loss
364 // is integrated for putting in event info and the number of collimators
365 // interacted with counted
366 if (info)
367 {FillEventInfo(info);}
368
371}
372
380
382 unsigned long long int nOriginalEventsIn,
383 unsigned long long int nEventsRequestedIn,
384 unsigned long long int nEventsInOriginalDistrFileIn,
385 unsigned long long int nEventsDistrFileSkippedIn,
386 unsigned int distrFileLoopNTimesIn)
387{
388 FillRunInfoAndUpdateHeader(info, nOriginalEventsIn, nEventsRequestedIn, nEventsInOriginalDistrFileIn, nEventsDistrFileSkippedIn, distrFileLoopNTimesIn);
392}
393
394G4bool BDSOutput::InvalidSamplerName(const G4String& samplerName)
395{
396 return protectedNames.find(samplerName) != protectedNames.end();
397}
398
399void BDSOutput::PrintProtectedNames(std::ostream& out)
400{
401 out << "Protected names for output " << G4endl;
402 for (const auto& key : protectedNames)
403 {out << "\"" << key << "\"" << G4endl;}
404}
405
407{
409 const BDSGlobalConstants* globalConstants = BDSGlobalConstants::Instance();
410
411 // Base root file name
412 G4String newFileName = baseFileName;
413
414 // if more than one file add number (starting at 0)
415 // of numberEventPerFile is specified and the number already generated exceeds that
416 if (numberEventPerFile > 0 && globalConstants->NGenerate() > numberEventPerFile)
417 {newFileName += "_" + std::to_string(outputFileNumber);} // note underscore
418
419 // policy: overwrite if output filename specifically set, otherwise increase number
420 // always check in interactive mode
421 if (!globalConstants->OutputFileNameSet() || !globalConstants->Batch())
422 {// check if file exists
423 G4String original = newFileName; // could have nper file number suffix too
424 G4int nTimeAppended = 1;
425 while (BDS::FileExists(newFileName + fileExtension)) // always test with extension
426 {// if exists increment suffix integer
427 newFileName = original + "-" + std::to_string(nTimeAppended);
428 nTimeAppended +=1;
429 }
430 }
431
432 // add extension now we've got the base part fixed
433 newFileName += fileExtension;
434
435 G4cout << __METHOD_NAME__ << "Setting up new file: " << newFileName << G4endl;
436
437 return newFileName;
438}
439
441{
442 // rounding up so last bin definitely covers smax
443 // (max - min) / bin width -> min = 0 here.
444 const G4double binWidth = BDSGlobalConstants::Instance()->ELossHistoBinWidth();
445 const BDSBeamline* flatBeamline = BDSAcceleratorModel::Instance()->BeamlineMain();
446 if (flatBeamline)
447 {// don't access a nullptr
448 if (!flatBeamline->empty())
449 {
450 G4double sMax = flatBeamline->GetLastItem()->GetSPositionEnd();
451 nbins = (int) std::ceil((sMax - sMinHistograms)/ binWidth); // round up to integer # of bins
452 }
453 }
454 else
455 {nbins = 1;} // can happen for generate primaries only
456
457 if (nbins == 0)
458 {nbins = 1;}
459
460 sMaxHistograms = sMinHistograms + nbins * binWidth;
461}
462
464{
465 // construct output histograms
466 // calculate histogram dimensions
468 const G4double smin = sMinHistograms / CLHEP::m;
469 const G4double smax = sMaxHistograms / CLHEP::m;
470#ifdef BDSDEBUG
471 G4cout << __METHOD_NAME__ << "histogram parameters calculated to be: " << G4endl;
472 G4cout << "s minimum: " << smin << " m" << G4endl;
473 G4cout << "s maximum: " << smax << " m" << G4endl;
474 G4cout << "# of bins: " << nbins << G4endl;
475#endif
476 // create the histograms
478 {
479 histIndices1D["Phits"] = Create1DHistogram("PhitsHisto","Primary Hits",nbins,smin,smax);
480 histIndices1D["Ploss"] = Create1DHistogram("PlossHisto","Primary Loss",nbins,smin,smax);
481 }
483 {histIndices1D["Eloss"] = Create1DHistogram("ElossHisto","Energy Loss",nbins,smin,smax);}
484 // prepare bin edges for a by-element histogram
485 std::vector<G4double> binedges;
486 const BDSBeamline* flatBeamline = BDSAcceleratorModel::Instance()->BeamlineMain();
487 if (flatBeamline) // can be nullptr in case of generate primaries only
488 {binedges = flatBeamline->GetEdgeSPositions();}
489 else
490 {binedges = {0,1};}
491 // create per element ("pe") bin width histograms
493 {
494 histIndices1D["PhitsPE"] = Create1DHistogram("PhitsPEHisto",
495 "Primary Hits per Element",
496 binedges);
497 histIndices1D["PlossPE"] = Create1DHistogram("PlossPEHisto",
498 "Primary Loss per Element",
499 binedges);
500 }
502 {
503 histIndices1D["ElossPE"] = Create1DHistogram("ElossPEHisto",
504 "Energy Loss per Element" ,
505 binedges);
506 }
508 {
509 histIndices1D["ElossVacuum"] = Create1DHistogram("ElossVacuumHisto",
510 "Energy Loss in Vacuum",
511 nbins,smin,smax);
512 histIndices1D["ElossVacuumPE"] = Create1DHistogram("ElossVaccumPEHisto",
513 "Energy Loss in Vacuum per Element" ,
514 binedges);
515 }
516
518 {
519 histIndices1D["PFirstAI"] = Create1DHistogram("PFirstAIHisto",
520 "Primary aperture impacts",
521 nbins, smin, smax);
522 }
523
524 // only create tunnel histograms if we build the tunnel
525 const BDSBeamline* tunnelBeamline = BDSAcceleratorModel::Instance()->TunnelBeamline();
526 if (!tunnelBeamline)
527 {
528 storeELossTunnel = false;
530 }
531 if (storeELossTunnelHistograms && tunnelBeamline)
532 {
533 binedges = tunnelBeamline->GetEdgeSPositions();
534 histIndices1D["ElossTunnel"] = Create1DHistogram("ElossTunnelHisto",
535 "Energy Loss in Tunnel",
536 nbins, smin,smax);
537 histIndices1D["ElossTunnelPE"] = Create1DHistogram("ElossTunnelPEHisto",
538 "Energy Loss in Tunnel per Element",
539 binedges);
540 }
541
543 {
544 std::vector<G4String> collHistNames = {"CollPhitsPE",
545 "CollPlossPE",
546 "CollElossPE",
547 "CollPInteractedPE"};
548 std::vector<G4String> collHistDesciptions = {"Primary Hits per Coll",
549 "Primary Loss per Coll",
550 "Energy Loss per Collimator",
551 "Primary Interacted per Collimator"};
552 for (G4int i = 0; i < (G4int)collHistNames.size(); i++)
553 {
554 histIndices1D[collHistNames[i]] = Create1DHistogram(collHistNames[i],
555 collHistDesciptions[i],
557 }
558 }
559
560 // one unique 'scorer' - single 3d histogram 3d
562 {
564 if (!BDS::IsFinite(g->XMax() - g->XMin()))
565 {throw BDSException(__METHOD_NAME__, "0 width in general 3D scoring histogram in x dimension - check options, xmin and xmax");}
566 if (!BDS::IsFinite(g->YMax() - g->YMin()))
567 {throw BDSException(__METHOD_NAME__, "0 width in general 3D scoring histogram in y dimension - check options, ymin and ymax");}
568 if (!BDS::IsFinite(g->ZMax() - g->ZMin()))
569 {throw BDSException(__METHOD_NAME__, "0 width in general 3D scoring histogram in z dimension - check options, zmin and zmax");}
570 if (g->NBinsX() <= 0)
571 {throw BDSException(__METHOD_NAME__, "invalid number of bins in x dimension of 3D scoring histogram - check option, nbinsx");}
572 if (g->NBinsY() <= 0)
573 {throw BDSException(__METHOD_NAME__, "invalid number of bins in y dimension of 3D scoring histogram - check option, nbinsx");}
574 if (g->NBinsZ() <= 0)
575 {throw BDSException(__METHOD_NAME__, "invalid number of bins in z dimension of 3D scoring histogram - check option, nbinsx");}
576
577 G4int scInd = Create3DHistogram("ScoringMap", "Energy Deposition",
578 g->NBinsX(), g->XMin()/CLHEP::m, g->XMax()/CLHEP::m,
579 g->NBinsY(), g->YMin()/CLHEP::m, g->YMax()/CLHEP::m,
580 g->NBinsZ(), g->ZMin()/CLHEP::m, g->ZMax()/CLHEP::m);
581 histIndices3D["ScoringMap"] = scInd;
582 }
583
584 // scoring maps
585 const std::map<G4String, BDSScorerHistogramDef> scorerHistogramDefs = BDSAcceleratorModel::Instance()->ScorerHistogramDefinitionsMap();
586 if (!scorerHistogramDefs.empty())
587 {
588 for (const auto& nameDef : scorerHistogramDefs)
589 {
590 const auto def = nameDef.second;
591 // use safe output name without any slashes in the name
592 G4int histID = -1;
593
594 if (def.nBinsE <=1)
595 {
596 if (def.geometryType == "box")
597 {
598 histID = Create3DHistogram(def.outputName, def.outputName,
599 def.nBinsX, def.xLow/CLHEP::m, def.xHigh/CLHEP::m,
600 def.nBinsY, def.yLow/CLHEP::m, def.yHigh/CLHEP::m,
601 def.nBinsZ, def.zLow/CLHEP::m, def.zHigh/CLHEP::m);
602 }
603 else if (def.geometryType == "cylindrical")
604 {
605 histID = Create3DHistogram(def.outputName, def.outputName,
606 def.nBinsZ, def.zLow/CLHEP::m, def.zHigh/CLHEP::m,
607 def.nBinsPhi, 0, CLHEP::twopi,
608 def.nBinsR, def.rInner / CLHEP::m, def.rOuter / CLHEP::m);
609 }
610
611 histIndices3D[def.uniqueName] = histID;
612 histIndexToUnits3D[histID] = def.primitiveScorerUnitValue;
613 // avoid using [] operator for map as we have no default constructor for BDSHistBinMapper3D
614 }
615 else
616 {
617 if (def.geometryType == "box")
618 {
619 histID = Create4DHistogram(def.outputName+"-"+def.eScale,def.outputName,def.eScale,def.eBinsEdges,
620 def.nBinsX, def.xLow/CLHEP::m, def.xHigh/CLHEP::m,
621 def.nBinsY, def.yLow/CLHEP::m, def.yHigh/CLHEP::m,
622 def.nBinsZ, def.zLow/CLHEP::m, def.zHigh/CLHEP::m,
623 def.nBinsE, def.eLow/CLHEP::GeV, def.eHigh/CLHEP::GeV);
624 }
625 else if (def.geometryType == "cylindrical")
626 {
627 histID = Create4DHistogram(def.outputName+"-"+def.eScale, def.outputName, def.eScale, def.eBinsEdges,
628 def.nBinsZ, def.zLow/CLHEP::m, def.zHigh/CLHEP::m,
629 def.nBinsPhi, 0, CLHEP::twopi,
630 def.nBinsR, def.rInner / CLHEP::m, def.rOuter / CLHEP::m,
631 def.nBinsE, def.eLow/CLHEP::GeV, def.eHigh/CLHEP::GeV);
632 }
633
634 histIndices4D[def.uniqueName] = histID;
635 histIndexToUnits4D[histID] = def.primitiveScorerUnitValue;
636 }
637 scorerCoordinateMaps.insert(std::make_pair(def.uniqueName, def.coordinateMapper));
638 }
639 }
640
641 G4int nBLMs = BDSBLMRegistry::Instance()->NBLMs();
642 if (nBLMs > 0)
643 {
644 // the same primitive scorers for BLMs may be used in multiple SDs (each representing
645 // a unique combination of primitive scorers. However, we want 1 histogram per primitive
646 // scorer for all BLMs. We want to fill the same scoring quantity into the one histogram
647 // even from different collections ("SD/PS"). Determine 'set' of histogram names, which is
648 // set of primitive scorers use for BLMs.
649 // note there may be scorers from general 3d meshes and not just blms
650 std::vector<G4String> psnamesc = BDSSDManager::Instance()->PrimitiveScorerNamesComplete();
651 std::vector<G4String> psnames = BDSSDManager::Instance()->PrimitiveScorerNames();
652 std::map<G4String, G4double> scorerUnits = BDSSDManager::Instance()->PrimitiveScorerUnits();
653 std::set<G4String> blmHistoNames;
654 std::map<G4String, G4String> psFullNameToPS;
655 for (const auto& scorerNameComplete : psnamesc)
656 {
657 if (BDS::StrContains(scorerNameComplete, "blm_"))
658 {
659 for (const auto& scorerName : psnames)
660 {
661 if (BDS::StrContains(scorerNameComplete, "/"+scorerName)) // only match end of full name with '/'
662 {
663 blmHistoNames.insert(scorerName);
664 psFullNameToPS[scorerNameComplete] = scorerName;
665 }
666 }
667 }
668 }
669
670 // make BLM histograms and map the full collection name to that histogram ID for easy filling
671 // at the end of event. Note, multiple collections may feed into the same histogram.
672 for (const auto &hn : blmHistoNames)
673 {
674 G4String blmHistName = "BLM_" + hn;
675 G4int hind = Create1DHistogram(blmHistName, blmHistName, nBLMs, 0, nBLMs);
676 histIndices1D[blmHistName] = hind;
677 histIndexToUnits1D[hind] = scorerUnits[hn];
678 for (const auto& kv : psFullNameToPS)
679 {
680 if (hn == kv.second)
681 {blmCollectionNameToHistogramID[kv.first] = hind;}
682 }
683 }
684 }
685}
686
712
713void BDSOutput::FillSamplerHitsVector(const std::vector<BDSHitsCollectionSampler*>& hits)
714{
715 for (const auto& hc : hits)
716 {
717 if (!hc)
718 {continue;} // could be nullptr
719 if (!(hc->entries() > 0))
720 {continue;}
721 for (int i = 0; i < (int) hc->entries(); i++)
722 {
723 const BDSHitSampler* hit = (*hc)[i];
724 G4int samplerID = hit->samplerID;
725 G4int samplerVectorIndex = samplerIDToIndexPlane[samplerID];
726 samplerTrees[samplerVectorIndex]->Fill(hit, storeSamplerMass, storeSamplerCharge,
729 }
730 }
731 // extra information - do only once at the end
732 if (storeSamplerIon)
733 {
734 for (auto& sampler : samplerTrees)
735 {sampler->FillIon();}
736 }
737}
738
739void BDSOutput::FillSamplerCylinderHitsVector(const std::vector<BDSHitsCollectionSamplerCylinder*>& hits)
740{
741 for (const auto& hc : hits)
742 {
743 if (!hc)
744 {continue;} // could be nullptr
745 if (!(hc->entries() > 0))
746 {continue;}
747 for (int i = 0; i < (int) hc->entries(); i++)
748 {
749 const BDSHitSamplerCylinder* hit = (*hc)[i];
750 G4int samplerID = hit->samplerID;
751 G4int samplerVectorIndex = samplerIDToIndexCylinder[samplerID];
752 samplerCTrees[samplerVectorIndex]->Fill(hit, storeSamplerMass, storeSamplerCharge,
755 }
756 }
757 // extra information - do only once at the end
758 if (storeSamplerIon)
759 {
760 for (auto& sampler : samplerCTrees)
761 {sampler->FillIon();}
762 }
763}
764
765void BDSOutput::FillSamplerSphereHitsVector(const std::vector<BDSHitsCollectionSamplerSphere*>& hits)
766{
767 for (const auto& hc : hits)
768 {
769 if (!hc)
770 {continue;} // could be nullptr
771 if (!(hc->entries() > 0))
772 {continue;}
773 for (int i = 0; i < (int) hc->entries(); i++)
774 {
775 const BDSHitSamplerSphere* hit = (*hc)[i];
776 G4int samplerID = hit->samplerID;
777 G4int samplerVectorIndex = samplerIDToIndexSphere[samplerID];
778 samplerSTrees[samplerVectorIndex]->Fill(hit, storeSamplerMass, storeSamplerCharge,
781 }
782 }
783 // extra information - do only once at the end
784 if (storeSamplerIon)
785 {
786 for (auto& sampler : samplerSTrees)
787 {sampler->FillIon();}
788 }
789}
790
791
793{
794 if (!(hits->entries() > 0))
795 {return;}
796 for (int i = 0; i < (int)hits->entries(); i++)
797 {
798 const BDSHitSampler* hit = (*hits)[i];
799 G4int samplerID = hit->samplerID;
800 G4int samplerVectorIndex = samplerIDToIndexPlane[samplerID];
801 samplerTrees[samplerVectorIndex]->Fill(hit, storeSamplerMass, storeSamplerCharge,
804 }
805
806 // extra information
807 if (storeSamplerIon)
808 {
809 for (auto& sampler : samplerTrees)
810 {sampler->FillIon();}
811 }
812}
813
815{
816 G4int nHits = (G4int)hits->entries();
817 if (nHits == 0) // integer so ok to compare
818 {return;}
819 for (G4int i = 0; i < nHits; i++)
820 {
821 const BDSHitSamplerLink* hit = (*hits)[i];
822 auto samplerIndex = samplerIDToIndexPlane.find(hit->samplerID);
823 if (samplerIndex == samplerIDToIndexPlane.end())
824 {throw BDSException(__METHOD_NAME__, "Sampler ID not found: " + std::to_string(hit->samplerID));}
826 }
827 // extra information - do only once at the end
828 if (storeSamplerIon)
829 {
830 for (auto& sampler : samplerTrees)
831 {sampler->FillIon();}
832 }
833}
834
835void BDSOutput::FillEnergyLoss(const BDSHitsCollectionEnergyDepositionGlobal* hits,
836 const LossType lossType)
837{
838 switch (lossType)
839 {
840 case BDSOutput::LossType::world:
841 case BDSOutput::LossType::worldexit:
842 case BDSOutput::LossType::worldcontents:
843 {break;}
844 default:
845 {return; break;} // don't fill for other types of hits
846 }
847
848 G4int nHits = (G4int)hits->entries();
849 if (nHits == 0) // integer so ok to compare
850 {return;}
851 switch (lossType)
852 {
853 case BDSOutput::LossType::world:
854 {
855 for (G4int i=0; i < nHits; i++)
856 {
857 BDSHitEnergyDepositionGlobal* hit = (*hits)[i];
858 energyDepositedWorld += hit->TotalEnergyWeighted()/CLHEP::GeV;
859 if (storeELossWorld)
860 {eLossWorld->Fill(hit);}
861 }
862 break;
863 }
864 case BDSOutput::LossType::worldexit:
865 {
866 for (G4int i = 0; i < nHits; i++)
867 {
868 BDSHitEnergyDepositionGlobal* hit = (*hits)[i];
869 energyWorldExit += hit->TotalEnergyWeighted()/CLHEP::GeV;
870 energyWorldExitKinetic += hit->KineticEnergyWeighted()/CLHEP::GeV;
871 if (storeELossWorld)
872 {eLossWorldExit->Fill(hit);}
873 }
874 break;
875 }
876 case BDSOutput::LossType::worldcontents:
877 {
878 for (G4int i = 0; i < nHits; i++)
879 {
880 BDSHitEnergyDepositionGlobal* hit = (*hits)[i];
881 energyDepositedWorldContents += hit->TotalEnergyWeighted()/CLHEP::GeV;
883 {eLossWorldContents->Fill(hit);}
884 }
885 break;
886 }
887 default:
888 {break;} // only to prevent compiler warning
889 }
890}
891
893 const LossType lossType)
894{
895 G4int nHits = (G4int)hits->entries();
896 if (nHits == 0)
897 {return;}
898 switch (lossType)
899 {
900 case BDSOutput::LossType::energy:
901 {
902 G4int indELoss = histIndices1D["Eloss"];
903 G4int indELossPE = histIndices1D["ElossPE"];
904 for (G4int i = 0; i < nHits; i++)
905 {
906 BDSHitEnergyDeposition* hit = (*hits)[i];
907 G4double sHit = hit->GetSHit() / CLHEP::m;
908 G4double eW = hit->GetEnergyWeighted() / CLHEP::GeV;
909 energyDeposited += eW;
910 if (storeELoss)
911 {eLoss->Fill(hit);}
913 {
914 runHistos->Fill1DHistogram(indELoss, sHit, eW);
915 evtHistos->Fill1DHistogram(indELoss, sHit, eW);
916 runHistos->Fill1DHistogram(indELossPE, sHit, eW);
917 evtHistos->Fill1DHistogram(indELossPE, sHit, eW);
918 }
919 }
920 break;
921 }
922 case BDSOutput::LossType::vacuum:
923 {
924 G4int indELossVacuum = storeELossVacuumHistograms ? histIndices1D["ElossVacuum"] : -1;
925 G4int indELossVacuumPE = storeELossVacuumHistograms ? histIndices1D["ElossVacuumPE"] : -1;
926 for (G4int i = 0; i < nHits; i++)
927 {
928 BDSHitEnergyDeposition* hit = (*hits)[i];
929 G4double sHit = hit->GetSHit() / CLHEP::m;
930 G4double eW = hit->GetEnergyWeighted() / CLHEP::GeV;
933 {eLossVacuum->Fill(hit);}
935 {
936 evtHistos->Fill1DHistogram(indELossVacuum, sHit, eW);
937 runHistos->Fill1DHistogram(indELossVacuumPE, sHit, eW);
938 }
939 }
940 break;
941 }
942 case BDSOutput::LossType::tunnel:
943 {
944 G4int indELossTunnel = storeELossTunnelHistograms ? histIndices1D["ElossTunnel"] : -1;
945 G4int indELossTunnelPE = storeELossTunnelHistograms ? histIndices1D["ElossTunnelPE"] : -1;
946 for (G4int i = 0; i < nHits; i++)
947 {
948 BDSHitEnergyDeposition *hit = (*hits)[i];
949 G4double sHit = hit->GetSHit() / CLHEP::m;
950 G4double eW = hit->GetEnergyWeighted() / CLHEP::GeV;
953 {eLossTunnel->Fill(hit);}
955 {
956 runHistos->Fill1DHistogram(indELossTunnel, sHit, eW);
957 evtHistos->Fill1DHistogram(indELossTunnel, sHit, eW);
958 runHistos->Fill1DHistogram(indELossTunnelPE, sHit, eW);
959 evtHistos->Fill1DHistogram(indELossTunnelPE, sHit, eW);
960 }
961 }
962 }
963 default:
964 {break;}
965 }
966
967 if (useScoringMap)
968 {
969 G4int indScoringMap = histIndices3D["ScoringMap"];
970 for (G4int i = 0; i < nHits; i++)
971 {
972 BDSHitEnergyDeposition *hit = (*hits)[i];
973 G4double sHit = hit->GetSHit() / CLHEP::m;
974 G4double eW = hit->GetEnergyWeighted() / CLHEP::GeV;
975 G4double x = hit->Getx() / CLHEP::m;
976 G4double y = hit->Gety() / CLHEP::m;
977 evtHistos->Fill3DHistogram(indScoringMap, x, y, sHit, eW);
978 runHistos->Fill3DHistogram(indScoringMap, x, y, sHit, eW);
979 }
980 }
981
983 nCollimators > 0 &&
984 (lossType == BDSOutput::LossType::energy) &&
986 {CopyFromHistToHist1D("ElossPE", "CollElossPE", collimatorIndices);}
987}
988
989void BDSOutput::FillPrimaryHit(const std::vector<const BDSTrajectoryPointHit*>& primaryHits)
990{
991 for (auto phit : primaryHits)
992 {
993 if (!phit)
994 {continue;}
995 pFirstHit->Fill(phit);
996 const G4double preStepSPosition = phit->point->GetPreS() / CLHEP::m;
998 {
999 runHistos->Fill1DHistogram(histIndices1D["Phits"], preStepSPosition);
1000 evtHistos->Fill1DHistogram(histIndices1D["Phits"], preStepSPosition);
1001 runHistos->Fill1DHistogram(histIndices1D["PhitsPE"], preStepSPosition);
1002 evtHistos->Fill1DHistogram(histIndices1D["PhitsPE"], preStepSPosition);
1003
1005 {CopyFromHistToHist1D("PhitsPE", "CollPhitsPE", collimatorIndices);}
1006 }
1007 }
1008}
1009
1010void BDSOutput::FillPrimaryLoss(const std::vector<const BDSTrajectoryPointHit*>& primaryLosses)
1011{
1012 for (auto ploss : primaryLosses)
1013 {
1014 if (!ploss)
1015 {continue;}
1016 pLastHit->Fill(ploss);
1017 const G4double postStepSPosition = ploss->point->GetPostS() / CLHEP::m;
1019 {
1020 runHistos->Fill1DHistogram(histIndices1D["Ploss"], postStepSPosition);
1021 evtHistos->Fill1DHistogram(histIndices1D["Ploss"], postStepSPosition);
1022 runHistos->Fill1DHistogram(histIndices1D["PlossPE"], postStepSPosition);
1023 evtHistos->Fill1DHistogram(histIndices1D["PlossPE"], postStepSPosition);
1024
1026 {CopyFromHistToHist1D("PlossPE", "CollPlossPE", collimatorIndices);}
1027 }
1028 }
1029}
1030
1032{
1033 if (storeTrajectory)
1035}
1036
1037void BDSOutput::FillCollimatorHits(const BDSHitsCollectionCollimator* hits,
1038 const std::vector<const BDSTrajectoryPointHit*>& primaryLossPoints)
1039{
1040 G4int nHits = (G4int)hits->entries();
1041 for (G4int i = 0; i < nHits; i++)
1042 {
1043 BDSHitCollimator* hit = (*hits)[i];
1044 G4int collimatorIndex = hit->collimatorIndex;
1045 collimators[collimatorIndex]->Fill(hit,
1046 collimatorInfo[collimatorIndex],
1047 collimatorDifferences[collimatorIndex],
1048 storeCollimatorHits); // this includes the || storeCollimatorHitsLinks || storeCollimatorHitsIons);
1049 }
1050
1051 // identify whether the primary loss point was in a collimator
1052 // only do if there's a beam line, ie finished in a beam line, and there are collimators
1053 if (!primaryLossPoints.empty())
1054 {
1055 for (auto primaryLossPoint : primaryLossPoints)
1056 {
1057 if (primaryLossPoint->point->GetBeamLine() && nCollimators > 0)
1058 {
1059 G4int lossPointBLInd = primaryLossPoint->point->GetBeamLineIndex(); // always the mass world index
1060 auto result = std::find(collimatorIndices.begin(), collimatorIndices.end(), lossPointBLInd);
1061 if (result != collimatorIndices.end())
1062 {
1063 G4int collIndex = (int) (result - collimatorIndices.begin());
1064 collimators[collIndex]->SetPrimaryStopped(true);
1065 collimators[collIndex]->primaryInteracted = true;
1066 // it must've interacted if it stopped - could be that we kill
1067 // secondaries and there's no energy deposition therefore not identified
1068 // as primaryInteracted=true in BDSOutputROOTEventCollimator::Fill()
1069 }
1070 }
1071 }
1072 }
1073
1074 // if required loop over collimators and get them to calculate and fill extra information
1076 {
1077 for (auto collimator : collimators)
1078 {collimator->FillExtras(storeCollimatorHitsIons, storeCollimatorHitsLinks);}
1079 }
1080
1081 // after all collimator hits have been filled, we summarise whether the primary
1082 // interacted in a histogram
1083 G4int histIndex = histIndices1D["CollPInteractedPE"];
1084 for (G4int i = 0; i < (G4int)collimators.size(); i++)
1085 {evtHistos->Fill1DHistogram(histIndex, i, (int)collimators[i]->primaryInteracted);}
1086
1087
1088 // loop over collimators and count the number that were interacted with in this event
1089 for (const auto collimator : collimators)
1090 {
1091 if (collimator->primaryInteracted)
1093 }
1094}
1095
1096void BDSOutput::FillApertureImpacts(const BDSHitsCollectionApertureImpacts* hits)
1097{
1099 {return;}
1100
1101 G4int nPrimaryImpacts = 0;
1102 G4int nHits = (G4int)hits->entries();
1103 G4int histIndex = histIndices1D["PFirstAI"];
1104 for (G4int i = 0; i < nHits; i++)
1105 {
1106 const BDSHitApertureImpact* hit = (*hits)[i];
1107 G4double eW = (hit->totalEnergy / CLHEP::GeV) * hit->weight;
1109 energyImpactingApertureKinetic += (hit->preStepKineticEnergy * hit->weight ) / CLHEP::GeV;
1110 if (hit->parentID == 0)
1111 {
1112 nPrimaryImpacts += 1;
1113 // only store one primary aperture hit in this histogram even if they were multiple
1114 if (storeApertureImpactsHistograms && nPrimaryImpacts == 1)
1115 {evtHistos->Fill1DHistogram(histIndex, hit->S / CLHEP::m);}
1116 }
1117 // hits are generated in order as the particle progresses
1118 // through the model, so the first one in the collection
1119 // for the primary is the first one in S.
1121 {apertureImpacts->Fill(hit, nPrimaryImpacts==1);}
1122 }
1123}
1124
1125void BDSOutput::FillScorerHits(const std::map<G4String, G4THitsMap<G4double>*>& scorerHitsMap)
1126{
1127 for (const auto& nameHitsMap : scorerHitsMap)
1128 {
1129#if G4VERSION < 1039
1130 if (nameHitsMap.second->GetSize() == 0)
1131#else
1132 if (nameHitsMap.second->size() == 0)
1133#endif
1134#ifdef BDSDEBUG
1135 {G4cout << nameHitsMap.first << " empty" << G4endl; continue;}
1136#else
1137 {continue;}
1138#endif
1139 FillScorerHitsIndividual(nameHitsMap.first, nameHitsMap.second);
1140 }
1141}
1142
1143void BDSOutput::FillScorerHitsIndividual(const G4String& histogramDefName,
1144 const G4THitsMap<G4double>* hitMap)
1145{
1146 if (BDS::StrContains(histogramDefName, "blm_"))
1147 {return FillScorerHitsIndividualBLM(histogramDefName, hitMap);}
1148
1149 if (!(histIndices3D.find(histogramDefName) == histIndices3D.end()))
1150 {
1151 G4int histIndex = histIndices3D[histogramDefName];
1152 G4double unit = BDS::MapGetWithDefault(histIndexToUnits3D, histIndex, 1.0);
1153 // avoid using [] operator for map as we have no default constructor for BDSHistBinMapper3D
1154 const BDSHistBinMapper& mapper = scorerCoordinateMaps.at(histogramDefName);
1155 TH3D* hist = evtHistos->Get3DHistogram(histIndex);
1156 G4int x,y,z,e;
1157#if G4VERSION < 1039
1158 for (const auto& hit : *hitMap->GetMap())
1159#else
1160 for (const auto& hit : *hitMap)
1161#endif
1162 {
1163 // convert from scorer global index to 3d i,j,k index of 3d scorer
1164 mapper.IJKLFromGlobal(hit.first, x,y,z,e);
1165 G4int rootGlobalIndex = (hist->GetBin(x + 1, y + 1, z + 1)); // convert to root system (add 1 to avoid underflow bin)
1166 evtHistos->Set3DHistogramBinContent(histIndex, rootGlobalIndex, *hit.second / unit);
1167 }
1169 }
1170
1171 if (!(histIndices4D.find(histogramDefName) == histIndices4D.end()))
1172 {
1173 G4int histIndex = histIndices4D[histogramDefName];
1174 G4double unit = BDS::MapGetWithDefault(histIndexToUnits4D, histIndex, 1.0);
1175 // avoid using [] operator for map as we have no default constructor for BDSHistBinMapper3D
1176 const BDSHistBinMapper& mapper = scorerCoordinateMaps.at(histogramDefName);
1177 G4int x,y,z,e;
1178#if G4VERSION < 1039
1179 for (const auto& hit : *hitMap->GetMap())
1180#else
1181 for (const auto& hit : *hitMap)
1182#endif
1183 {
1184 // convert from scorer global index to 4d i,j,k,e index of 4d scorer
1185 mapper.IJKLFromGlobal(hit.first, x,y,z,e);
1186 evtHistos->Set4DHistogramBinContent(histIndex, x, y, z, e - 1, *hit.second / unit); // - 1 to go back to the Boost Histogram indexing (-1 for the underflow bin)
1187 }
1188 runHistos->AccumulateHistogram4D(histIndex, evtHistos->Get4DHistogram(histIndex));
1189 }
1190}
1191
1192void BDSOutput::FillScorerHitsIndividualBLM(const G4String& histogramDefName,
1193 const G4THitsMap<G4double>* hitMap)
1194{
1195 G4int histIndex = blmCollectionNameToHistogramID[histogramDefName];
1196#if G4VERSION < 1039
1197 for (const auto& hit : *hitMap->GetMap())
1198#else
1199 for (const auto& hit : *hitMap)
1200#endif
1201 {
1202#ifdef BDSDEBUG
1203 G4cout << "Filling hist " << histIndex << ", bin: " << hit.first+1 << " value: " << *hit.second << G4endl;
1204#endif
1205 G4double unit = BDS::MapGetWithDefault(histIndexToUnits1D, histIndex, 1.0);
1206 evtHistos->Fill1DHistogram(histIndex,hit.first, *hit.second / unit);
1207 runHistos->Fill1DHistogram(histIndex,hit.first, *hit.second / unit);
1208 }
1209}
1210
1212 unsigned long long int nOriginalEventsIn,
1213 unsigned long long int nEventsRequestedIn,
1214 unsigned long long int nEventsInOriginalDistrFileIn,
1215 unsigned long long int nEventsDistrFileSkippedIn,
1216 unsigned int distrFileLoopNTimesIn)
1217{
1218 if (info)
1220 // Note, check analysis/HeaderAnalysis.cc if the logic changes of only filling the 2nd
1221 // entry in the header tree with this information
1222 headerOutput->nOriginalEvents = nOriginalEventsIn;
1223 headerOutput->nEventsRequested = nEventsRequestedIn;
1224 headerOutput->nEventsInFile = nEventsInOriginalDistrFileIn;
1225 headerOutput->nEventsInFileSkipped = nEventsDistrFileSkippedIn;
1226 headerOutput->distrFileLoopNTimes = distrFileLoopNTimesIn;
1227}
1228
1229void BDSOutput::CopyFromHistToHist1D(const G4String& sourceName,
1230 const G4String& destinationName,
1231 const std::vector<G4int>& indices)
1232{
1233 TH1D* sourceEvt = evtHistos->Get1DHistogram(histIndices1D[sourceName]);
1234 TH1D* destinationEvt = evtHistos->Get1DHistogram(histIndices1D[destinationName]);
1235 // for the run ones we are overwriting but this is ok
1236 TH1D* sourceRun = runHistos->Get1DHistogram(histIndices1D[sourceName]);
1237 TH1D* destinationRun = runHistos->Get1DHistogram(histIndices1D[destinationName]);
1238 G4int binIndex = 1; // starts at 1 for TH1; 0 is underflow
1239 for (const auto index : indices)
1240 {
1241 destinationEvt->SetBinContent(binIndex, sourceEvt->GetBinContent(index + 1));
1242 destinationEvt->SetBinError(binIndex, sourceEvt->GetBinError(index + 1));
1243 destinationRun->SetBinContent(binIndex, sourceRun->GetBinContent(index + 1));
1244 destinationRun->SetBinError(binIndex, sourceRun->GetBinError(index + 1));
1245 binIndex++;
1246 }
1247}
const std::map< G4String, BDSScorerHistogramDef > & ScorerHistogramDefinitionsMap() const
Access all scorer histogram definitions.
const std::map< G4String, G4Transform3D > & ScorerMeshPlacementsMap() const
Access all scorer histogram definitions.
BDSBeamline * TunnelBeamline() const
Access the beam line containing all the tunnel segments.
const BDSBeamline * BeamlineMain() const
Accessor.
static BDSBLMRegistry * Instance()
Accessor for registry.
G4double GetSPositionEnd() const
Accessor.
A vector of BDSBeamlineElement instances - a beamline.
std::vector< G4double > GetEdgeSPositions() const
const BDSBeamlineElement * GetLastItem() const
Return a reference to the last element.
G4bool empty() const
Iterator mechanics.
Interface to store event information use G4 hooks.
const BDSOutputROOTEventInfo * GetInfo() const
Accessor.
General exception with possible name of object and message.
A class that holds global options and constants.
static BDSGlobalConstants * Instance()
Access method.
BDS::TrajectoryOptions StoreTrajectoryOptions() const
options that require some implementation.
G4bool UseImportanceSampling() const
Is importance sampling being used.
Mapping from axis indices to 1D index.
Snapshot of information for particle passing through a collimator.
Snapshot of information for particle passing through a collimator.
G4int collimatorIndex
Index of collimator the hit is in.
Information recorded for a step leaving a volume.
Information recorded for a single piece of energy deposition.
G4double Getx() const
Accessor for extra piece of information.
G4double Gety() const
Accessor for extra piece of information.
The information recorded from a particle impacting a sampler.
The information recorded from a particle impacting a sampler.
The information recorded from a particle impacting a sampler.
G4int A() const
Accessor.
G4int Z() const
Accessor.
Class to store all beam options for a BDSIM run.
void Fill(const BDSOutputROOTEventCoords *other)
Fill from another instance.
unsigned long long int nEventsRequested
Number of events requested to be simulated from the file.
unsigned int distrFileLoopNTimes
Number of times a distribution file was replayed.
unsigned long long int nEventsInFileSkipped
Number of events from distribution file that were skipped due to filters.
unsigned long long int nOriginalEvents
Number of original events if skimmed.
void Fill(const std::vector< std::string > &analysedFilesIn=std::vector< std::string >(), const std::vector< std::string > &combinedFilesIn=std::vector< std::string >())
unsigned long long int nEventsInFile
Number of events in the input distribution file irrespective of filters.
void AccumulateHistogram3D(G4int histoId, TH3D *otherHistogram)
Add the values from one supplied 3D histogram to another. Uses TH3-Add().
BDSBH4DBase * Get4DHistogram(int iHisto) const
Accessors.
TH1D * Get1DHistogram(int iHisto) const
Accessors.
void Set3DHistogramBinContent(G4int histoId, G4int globalBinID, G4double value)
TH3D * Get3DHistogram(int iHisto) const
Accessors.
double energyKilled
Total energy of killed particles that weren't in a sensitive volume.
double energyWorldExitKinetic
Total kinetic energy leaving the world.
double energyWorldExit
Total energy leaving the world.
double energyDepositedWorldContents
Total energy deposited in the world contents for this event.
double energyImpactingApertureKinetic
Total kinetic energy impacting the aperture.
double energyDepositedWorld
Total energy deposited in the world for this event.
double energyDepositedTunnel
Total energy deposited in the tunnel for this event.
double energyDepositedVacuum
Total energy deposited in vacuum volumes.
int nCollimatorsInteracted
Number of collimators primary interacted with.
double energyTotal
Sum of above 5 variables that totals all energy.
double energyDeposited
Total energy deposited in machine (not world or tunnel).
double energyImpactingAperture
Total energy impacting the aperture.
void Fill(const BDSOutputROOTEventLoss *other)
Fill from another instance.
virtual void Fill(const std::vector< G4int > &collimatorIndicesIn={}, const std::map< G4String, G4int > &collimatorIndicesByNameIn={}, const std::vector< BDSOutputROOTEventCollimatorInfo > &collimatorInfoIn={}, const std::vector< G4String > &collimatorBranchNamesIn={}, const std::vector< G4int > &cavityIndicesIn={}, const std::map< G4String, G4int > &cavityIndicesByNameIn={}, const std::vector< BDSOutputROOTEventCavityInfo > &cavityInfoIn={}, const std::vector< G4String > &cavityBranchNamesIn={}, const std::map< G4String, G4Transform3D > *scorerMeshPlacements=nullptr, const std::map< short int, G4String > *materialIDToNameUnique=nullptr, G4bool storeTrajectory=false)
Fill root output.
Class to store all options for a BDSIM run.
Information pertaining to a run.
Information stored per sampler per event.
void Fill(G4bool fillIons)
Fill maps of particle information from Geant4.
virtual void Flush()
Clear maps.
Holder for output information.
void InitialiseCollimators()
Construct collimators.
BDSOutputROOTEventModel * modelOutput
Model output.
G4int Create1DHistogram(G4String name, G4String title, G4int nbins, G4double xmin, G4double xmax)
Create histograms for both evtHistos and runHistos. Return index from evtHistos.
std::vector< G4String > collimatorNames
Names of collimators in output structures.
std::vector< BDSOutputROOTEventCollimator * > collimators
Collimator output structures.
BDSOutputROOTEventSampler< double > * primary
Primary sampler structure.
BDSOutputROOTEventRunInfo * runInfo
Run information.
void InitialiseMaterialMap()
Construct a map of material pointer to integer ID and name.
void ClearStructuresOptions()
Clear the local options structure.
std::vector< G4String > cavityNames
Names of cavities in output structures.
BDSOutputROOTEventHistograms * runHistos
Run level histograms.
BDSOutputROOTEventLossWorld * eLossWorldExit
World exit hits.
std::vector< G4int > cavityIndices
Indices in beam line that are cavities.
void ClearStructuresRunLevel()
Clear the local structures in this class in preparation for a new run.
void InitialiseSamplers()
Construct samplers.
void ClearStructuresBeam()
Clear the local beam structure.
std::vector< BDSOutputROOTEventCavityInfo > cavityInfo
Cavity parameters.
std::map< G4String, G4int > collimatorIndicesByName
Indices mapped to their name.
BDSOutputROOTEventLossWorld * eLossWorldContents
Externally supplied world contents hits.
G4int nCollimators
Number of collimators in beam line.
std::vector< BDSOutputROOTEventSampler< double > * > samplerTrees
Sampler structures.
std::vector< std::pair< G4double, G4double > > collimatorDifferences
void ClearStructuresModel()
Clear the local model structure.
void ClearStructuresHeader()
Clear the local header structure.
G4int Create4DHistogram(const G4String &name, const G4String &title, const G4String &eScale, const std::vector< double > &eBinsEdges, G4int nBinsX, G4double xMin, G4double xMax, G4int nBinsY, G4double yMin, G4double yMax, G4int nBinsZ, G4double zMin, G4double zMax, G4int nBinsE, G4double eMin, G4double eMax)
Create histograms for both evtHistos and runHistos. Return index from evtHistos.
BDSOutputROOTEventHeader * headerOutput
Information about the file.
BDSOutputROOTEventLossWorld * eLossWorld
World energy deposition.
BDSOutputROOTEventLoss * eLossVacuum
General energy deposition.
std::vector< G4int > collimatorIndices
Indices in beam line that are collimators.
BDSOutputROOTEventInfo * evtInfo
Event information.
BDSOutputROOTEventLoss * pLastHit
Primary loss point.
BDSOutputROOTEventHistograms * evtHistos
Event level histograms.
BDSOutputROOTEventLoss * eLossTunnel
Tunnel energy deposition.
G4int Create3DHistogram(G4String name, G4String title, G4int nBinsX, G4double xMin, G4double xMax, G4int nBinsY, G4double yMin, G4double yMax, G4int nBinsZ, G4double zMin, G4double zMax)
Create histograms for both evtHistos and runHistos. Return index from evtHistos.
void ClearStructuresEventLevel()
Clear the local structures in this class in preparation for a new event.
BDSOutputROOTEventLoss * pFirstHit
Primary hit point.
BDSOutputROOTEventTrajectory * traj
Trajectories.
BDSOutputROOTEventBeam * beamOutput
Beam output.
BDSOutputROOTEventLoss * eLoss
General energy deposition.
std::vector< BDSOutputROOTEventCollimatorInfo > collimatorInfo
void PrepareCavityInformation()
Extract number of collimators and their names from beam line.
BDSOutputROOTEventAperture * apertureImpacts
Impacts on the aperture.
BDSOutputROOTParticleData * particleDataOutput
Geant4 information / particle tables.
BDSOutputROOTEventOptions * optionsOutput
Options output.
std::map< G4String, G4int > cavityIndicesByName
Indices mapped to their name.
virtual void WriteModel()=0
Write a representation of the samplers and beamline.
void FillEnergyLoss(const BDSHitsCollectionEnergyDeposition *loss, const LossType type)
Fill a collection of energy hits into the appropriate output structure.
Definition BDSOutput.cc:892
G4double energyDepositedVacuum
Integral when filling hit.
Definition BDSOutput.hh:342
virtual void WriteParticleData()=0
Write the geant4 information.
G4bool createCollimatorOutputStructures
Definition BDSOutput.hh:338
virtual void WriteBeam()=0
Write the beam.
virtual void NewFile()=0
Open a new file. This should call WriteHeader() in it.
G4bool storeCollimatorHitsIons
Storage option.
Definition BDSOutput.hh:318
G4bool storeSamplerCharge
Storage option.
Definition BDSOutput.hh:326
G4bool storeSamplerRigidity
Storage option.
Definition BDSOutput.hh:329
virtual void WriteFileEventLevel()=0
BDSOutput()=delete
No default constructor.
G4bool storePerEventHistos
Options for dynamic bits of output.
Definition BDSOutput.hh:178
G4bool storeCollimatorHitsLinks
Storage option.
Definition BDSOutput.hh:317
G4bool storeELossHistograms
Storage option.
Definition BDSOutput.hh:319
G4bool storePrimaryHistograms
Storage option.
Definition BDSOutput.hh:323
G4double energyDepositedTunnel
Integral when filling hit.
Definition BDSOutput.hh:345
G4bool storeSamplerKineticEnergy
Storage option.
Definition BDSOutput.hh:327
void CloseAndOpenNewFile()
Close a file and open a new one.
Definition BDSOutput.cc:373
void FillEventInfo(const BDSEventInfo *info)
Fill event summary information.
Definition BDSOutput.cc:687
virtual void WriteOptions()=0
Write the options.
G4bool storeCavityInfo
Storage option.
Definition BDSOutput.hh:314
std::map< G4String, G4int > blmCollectionNameToHistogramID
Definition BDSOutput.hh:185
std::map< G4int, G4double > histIndexToUnits1D
Definition BDSOutput.hh:362
G4bool storePrimaries
Options for dynamic bits of output.
Definition BDSOutput.hh:176
G4bool storeSamplerPolarCoords
Storage option.
Definition BDSOutput.hh:325
void FillScorerHitsIndividual(const G4String &hsitogramDefName, const G4THitsMap< G4double > *hitMap)
Fill an individual scorer hits map into a particular output histogram.
const G4String baseFileName
Base file name.
Definition BDSOutput.hh:294
void FillSamplerHitsVector(const std::vector< BDSHitsCollectionSampler * > &hits)
Fill sampler hits from a vector<sampler hits collection>.
Definition BDSOutput.cc:713
G4bool storeTrajectory
Options for dynamic bits of output.
Definition BDSOutput.hh:177
void FillSamplerHitsLink(const BDSHitsCollectionSamplerLink *hits)
Fill sampler link hits into output structures.
Definition BDSOutput.cc:814
G4int nbins
Number of bins for each histogram required.
Definition BDSOutput.hh:311
G4bool useScoringMap
Whether the single 3D histogram will be built.
Definition BDSOutput.hh:303
void CopyFromHistToHist1D(const G4String &sourceName, const G4String &destinationName, const std::vector< G4int > &indices)
G4String GetNextFileName()
Get the next file name based on the base file name and the accrued number of files.
Definition BDSOutput.cc:406
virtual void InitialiseGeometryDependent()
Definition BDSOutput.cc:170
void FillPrimary(const G4PrimaryVertex *vertex, const G4int turnsTaken)
Definition BDSOutput.cc:245
G4double energyDepositedWorldContents
Integral when filling hit.
Definition BDSOutput.hh:344
const G4String fileExtension
File extension to add to each file.
Definition BDSOutput.hh:295
G4bool storeSamplerIon
Storage option.
Definition BDSOutput.hh:330
G4bool storeModel
Storage option.
Definition BDSOutput.hh:324
void FillRun(const BDSEventInfo *info, unsigned long long int nOriginalEventsIn, unsigned long long int nEventsRequestedIn, unsigned long long int nEventsInOriginalDistrFileIn, unsigned long long int nEventsDistrFileSkippedIn, unsigned int distrFileLoopNTimesIn)
Copy run information to output structure.
Definition BDSOutput.cc:381
G4double energyWorldExitKinetic
Integral when filling hit.
Definition BDSOutput.hh:349
std::map< G4String, G4int > histIndices1D
Map of histogram name (short) to index of histogram in output.
Definition BDSOutput.hh:354
void FillTrajectories(const BDSTrajectoriesToStore *trajectories)
Copy a set of trajectories to the output structure.
G4bool storeELoss
Options for dynamic bits of output.
Definition BDSOutput.hh:169
void FillParticleData(G4bool writeIons)
Fill the local structure particle data with information. Also calls WriteParticleData().
Definition BDSOutput.cc:192
G4bool storeParticleData
Storage option.
Definition BDSOutput.hh:322
G4bool storeApertureImpactsHistograms
Options for dynamic bits of output.
Definition BDSOutput.hh:175
G4double energyImpactingApertureKinetic
Integral when filling hit.
Definition BDSOutput.hh:347
G4double energyImpactingAperture
Integral when filling hit.
Definition BDSOutput.hh:346
void FillEventPrimaryOnly(const BDSParticleCoordsFullGlobal &coords, const BDSParticleDefinition *particle)
Definition BDSOutput.cc:272
G4bool storeELossWorldContents
Options for dynamic bits of output.
Definition BDSOutput.hh:173
G4bool storeCollimatorInfo
Storage option.
Definition BDSOutput.hh:315
virtual void WriteFileRunLevel()=0
void FillBeam(const GMAD::BeamBase *beam)
Definition BDSOutput.cc:210
virtual void WriteHeaderEndOfFile()=0
Overwrite and update header in the output.
void FillHeader()
Fill the local structure header with information - updates time stamp.
Definition BDSOutput.cc:184
void FillPrimaryLoss(const std::vector< const BDSTrajectoryPointHit * > &primaryLosses)
Fill a collection volume exit hits into the appropriate output structure.
static void PrintProtectedNames(std::ostream &out)
Feedback for protected names.
Definition BDSOutput.cc:399
std::map< G4String, G4int > histIndices4D
Map of histogram name (short) to index of histogram in output.
Definition BDSOutput.hh:356
void FillPrimaryHit(const std::vector< const BDSTrajectoryPointHit * > &primaryHits)
Fill the hit where the primary particle impact.
Definition BDSOutput.cc:989
void FillRunInfoAndUpdateHeader(const BDSEventInfo *info, unsigned long long int nOriginalEventsIn, unsigned long long int nEventsRequestedIn, unsigned long long int nEventsInOriginalDistrFileIn, unsigned long long int nEventsDistrFileSkippedIn, unsigned int distrFileLoopNTimesIn)
G4int outputFileNumber
Number of output file.
Definition BDSOutput.hh:297
void FillApertureImpacts(const BDSHitsCollectionApertureImpacts *hits)
Fill aperture impact hits.
void FillSamplerHits(const BDSHitsCollectionSampler *hits)
Fill sampler hits into output structures.
Definition BDSOutput.cc:792
G4bool storeELossWorld
Options for dynamic bits of output.
Definition BDSOutput.hh:172
void FillEvent(const BDSEventInfo *info, const G4PrimaryVertex *vertex, const std::vector< BDSHitsCollectionSampler * > &samplerHitsPlane, const std::vector< BDSHitsCollectionSamplerCylinder * > &samplerHitsCylinder, const std::vector< BDSHitsCollectionSamplerSphere * > &samplerHitsSphere, const BDSHitsCollectionSamplerLink *samplerHitsLink, const BDSHitsCollectionEnergyDeposition *energyLoss, const BDSHitsCollectionEnergyDeposition *energyLossFull, const BDSHitsCollectionEnergyDeposition *energyLossVacuum, const BDSHitsCollectionEnergyDeposition *energyLossTunnel, const BDSHitsCollectionEnergyDepositionGlobal *energyLossWorld, const BDSHitsCollectionEnergyDepositionGlobal *energyLossWorldContents, const BDSHitsCollectionEnergyDepositionGlobal *worldExitHits, const std::vector< const BDSTrajectoryPointHit * > &primaryHits, const std::vector< const BDSTrajectoryPointHit * > &primaryLosses, const BDSTrajectoriesToStore *trajectories, const BDSHitsCollectionCollimator *collimatorHits, const BDSHitsCollectionApertureImpacts *apertureImpactHits, const std::map< G4String, G4THitsMap< G4double > * > &scorerHitsMap, const G4int turnsTaken)
Copy event information from Geant4 simulation structures to output structures.
Definition BDSOutput.cc:298
void CreateHistograms()
Create histograms.
Definition BDSOutput.cc:463
G4int storeTrajectoryStepPoints
Storage option.
Definition BDSOutput.hh:331
G4bool storeTrajectoryStepPointLast
Storage option.
Definition BDSOutput.hh:332
G4bool storeELossVacuum
Options for dynamic bits of output.
Definition BDSOutput.hh:171
std::map< G4String, BDSHistBinMapper > scorerCoordinateMaps
Map of histogram name (short) to index of histogram in output.
Definition BDSOutput.hh:357
G4bool storeSamplerMass
Storage option.
Definition BDSOutput.hh:328
void FillModel()
Definition BDSOutput.cc:224
G4double energyWorldExit
Integral when filling hit.
Definition BDSOutput.hh:348
G4int nCollimatorsInteracted
Integral when filling hit.
Definition BDSOutput.hh:350
void FillOptions(const GMAD::OptionsBase *options)
Definition BDSOutput.cc:217
G4bool storeELossVacuumHistograms
Storage option.
Definition BDSOutput.hh:321
LossType
Enum for different types of energy loss that can be written out.
Definition BDSOutput.hh:189
void CalculateHistogramParameters()
Calculate the number of bins and required maximum s.
Definition BDSOutput.cc:440
G4bool storeELossTunnel
Options for dynamic bits of output.
Definition BDSOutput.hh:170
G4double energyDeposited
Integral when filling hit.
Definition BDSOutput.hh:341
static const std::set< G4String > protectedNames
Invalid names for samplers - kept here as this is where the output structures are created.
Definition BDSOutput.hh:89
G4int numberEventPerFile
Number of events stored per file.
Definition BDSOutput.hh:296
G4double energyDepositedWorld
Integral when filling hit.
Definition BDSOutput.hh:343
G4bool storeCollimatorHits
Storage option.
Definition BDSOutput.hh:316
void FillScorerHits(const std::map< G4String, G4THitsMap< G4double > * > &scorerHitsMap)
Fill a map of scorer hits into the output.
static G4bool InvalidSamplerName(const G4String &samplerName)
Test whether a sampler name is invalid or not.
Definition BDSOutput.cc:394
void FillCollimatorHits(const BDSHitsCollectionCollimator *hits, const std::vector< const BDSTrajectoryPointHit * > &primaryLossPoints)
Fill collimator hits.
BDS::TrajectoryOptions storeTrajectoryOptions
Storage option.
Definition BDSOutput.hh:333
std::map< G4String, G4int > histIndices3D
Map of histogram name (short) to index of histogram in output.
Definition BDSOutput.hh:355
G4bool storeApertureImpacts
Options for dynamic bits of output.
Definition BDSOutput.hh:174
virtual void CloseFile()=0
G4double sMinHistograms
Definition BDSOutput.hh:307
G4bool storeELossTunnelHistograms
Storage option.
Definition BDSOutput.hh:320
virtual void WriteHeader()=0
Write the header.
A set of particle coordinates in both local and global.
Wrapper for particle definition.
G4double Mass() const
Accessor.
G4bool NElectrons() const
Accessor.
G4double Momentum() const
Accessor.
G4double Charge() const
Accessor.
G4double BRho() const
Accessor.
BDSIonDefinition * IonDefinition() const
Accessor.
G4bool IsAnIon() const
Accessor.
Full set of coordinates for association with primary vertex. Vector version.
Full set of coordinates for association with primary vertex.
const std::map< G4String, G4double > & PrimitiveScorerUnits() const
Access the map of units for primitive scorers.
const std::vector< G4String > & PrimitiveScorerNames() const
Access a vector of the just primitive scorer part of the names.
const std::vector< G4String > & PrimitiveScorerNamesComplete() const
Access a vector the full primitive scorer names as registered.
Double map of trajectories to bitset of which filters matched whether to store them.
Options for a beam distribution.
Definition beamBase.h:34
Basic options class independent of Geant4.
Definition optionsBase.h:35
G4bool StrContains(const G4String &str, const G4String &test)
Utility function to simplify lots of syntax changes for pedantic g4 changes.
V MapGetWithDefault(const std::map< K, V > &m, const K &key, const V &defaultValue)
G4bool FileExists(const G4String &filename)
Checks if filename exists.
G4bool IsFinite(G4double value, G4double tolerance=std::numeric_limits< double >::epsilon())