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