ATLAS Offline Software
ArrayBM.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #include <algorithm> /*count_if,max_element*/
6 #include <cassert>
7 #include <cmath> /*ceil,floor*/
8 #include <numeric> /*accumulate*/
9 
10 // Random Number Generation
12 #include "CLHEP/Random/RandomEngine.h"
13 #include "CLHEP/Random/RandGeneral.h"
14 
16 
17 #include "UtilityFuncs.h"
18 #include "ArrayBM.h"
19 
20 ArrayBM::ArrayBM(const std::string& name,ISvcLocator* svc)
21  : base_class(name,svc)
22  , m_maxBunchCrossingPerOrbit(3564)
23  , m_t0Offset(0)
24  , m_intensityPatternProp()
25  , m_ipLength(1)
26  , m_intensityPattern(new double[m_ipLength])
27  , m_biRandom(nullptr)
28  , m_largestElementInPattern(1.0)
29  , m_signalPattern(nullptr)
30 {
31  declareProperty("MaxBunchCrossingPerOrbit", m_maxBunchCrossingPerOrbit, "The number of slots in each LHC beam. Default: 3564.");
32  declareProperty("IntensityPattern", m_intensityPatternProp,
33  "An array of floats containing the beam intensity distribution as a function of time in bins of 25ns. ArrayBM normalizes the distribution and uses it as a stencil to determine the relative intensity at each beam xing in the simulated range"
34  );
35  declareProperty("EmptyBunchOption", m_emptyBunches=0, "Option for empty bunches. 0: normal treatment. Positive N: first N BCIDs after filled. Negative N: any empty BCID is allowed.");
36  m_intensityPattern[0]=1.0;
37 }
38 
40 {
41  delete [] m_intensityPattern;
42  delete m_biRandom;
43 }
44 
46 {
47  if (m_seed == 0u) {
48  // Only need AthRNGSvc if seed is set to 0
49  ATH_CHECK(m_randomSvc.retrieve());
50  m_rngWrapper = m_randomSvc->getEngine(this);
51  }
52 
53  // Need to copy to make modifications for empty bunches
54  const std::vector<float>& rProp(m_intensityPatternProp.value());
55  std::vector<float>::const_iterator pBegin(rProp.begin());
56  std::vector<float>::const_iterator pEnd(rProp.end());
57  m_ipLength = rProp.size();
58  // Consistency checks
60  {
61  ATH_MSG_ERROR("IntensityPattern length (" << m_ipLength << "), exceeds the maximum number of bunch crossings per orbit (" << m_maxBunchCrossingPerOrbit << ").");
62  return StatusCode::FAILURE;
63  }
64 
65  // Initialize the signal pattern if we need one different from the intensity pattern
66  if (m_signalPattern) delete [] m_signalPattern;
67  if (m_emptyBunches!=0){
68  m_signalPattern = new double[m_ipLength];
69  }
70  // Modification for empty bunches option
71  if (m_emptyBunches<0 || std::abs(m_emptyBunches)>static_cast<int>(m_ipLength)){
72  // Easy case: Just flip all the bunches
73  for (size_t i=0;i<m_ipLength;++i){
74  if (rProp[i]>0.) m_signalPattern[i]=0.;
75  else m_signalPattern[i]=1.;
76  } // Loop over all bunches in the pattern
77  } else if (m_emptyBunches>0){
78  // Harder case: N BCIDs after filled
79  int sinceFilled=0;
80  // Set sinceFilled for the beginning of the pattern; assume we will not wrap (otherwise caught above)
81  for (size_t i=m_ipLength-m_emptyBunches;i<m_ipLength;++i){
82  if (rProp[i]>0) sinceFilled=0;
83  else sinceFilled+=1;
84  } // Done with the loop over previous BCIDs
85  // Now do the loop setting the intensity pattern
86  for (size_t i=0;i<m_ipLength;++i){
87  if (rProp[i]>0){
88  // Filled BCID. Reset count, don't allow signal.
89  sinceFilled=0;
90  m_signalPattern[i]=0.;
91  } else if (sinceFilled<m_emptyBunches){
92  // First N BCIDs. Increment count, allow signal.
93  sinceFilled+=1;
94  m_signalPattern[i]=1.;
95  } else {
96  // Beyond N BCIDs. Increment count, don't allow signal.
97  sinceFilled+=1;
98  m_signalPattern[i]=0.;
99  }
100  } // Done with loop over previous BCIDs
101  }
102 
103  // Normalise the pattern so that the non-zero elements average to 1.0
104  float nonZeroElementCount(static_cast<float>(std::count_if(pBegin, pEnd, IsNonZero)));
105  if(nonZeroElementCount<1.0)
106  {
107  ATH_MSG_ERROR("IntensityPattern has no non-zero elements!");
108  return StatusCode::FAILURE;
109  }
110  float elementSum(static_cast<float>(std::accumulate(pBegin, pEnd,0.0)));
111  float denominator(elementSum/nonZeroElementCount);
112 
113  // Normalise the pattern so that the highest element value is 1.0
114  float maxElement(*(std::max_element(pBegin, pEnd)));
115  float inv_maxElement = maxElement != 0 ? 1. / maxElement : 1;
116 
117  // Copy normalized intensity pattern from the property
118  delete [] m_intensityPattern;
119  m_intensityPattern = new double[m_ipLength];
120  for (unsigned int i=0; i<m_ipLength; ++i)
121  {
122  if (rProp[i]<0.0)
123  {
124  ATH_MSG_ERROR("All IntensityPattern elements must be >=0. Please fix element #" << i );
125  return StatusCode::FAILURE;
126  }
127  m_intensityPattern[i] = rProp[i] * inv_maxElement; // this ensures that the elements are all in the range [0,1]
128  }
129  // If we don't want to have signal in empty crossings, then our signal pattern is just the intensity pattern
130  if (m_emptyBunches==0){
132  }
133 
134  // Will be used to convert values in the m_intensityPattern
135  // from having max value 1.0 to having mean value 1.0
136  m_largestElementInPattern = (maxElement/denominator);
137 
138  // FIXME add a check that entry 0 is zero? In data, BCID=1 is always the
139  // first filled bunch.
140 
141  if (m_seed == 0u) {
142  delete m_biRandom;
143  // the engine is created if not there already
144  m_biRandom =
145  new CLHEP::RandGeneral(m_signalPattern, m_ipLength,
146  /*IntType=*/1); // discrete distribution
147  } else {
148  m_t0Dist =
149  std::make_unique<boost::random::discrete_distribution<unsigned int>>(
151  }
152  return StatusCode::SUCCESS;
153 }
154 
155 void ArrayBM::selectT0(unsigned int run, unsigned long long event)
156 {
157  if (m_seed == 0u) {
158  // Use AthRNGSvc
159  const EventContext& ctx =
160  Gaudi::Hive::currentContext(); // not ideal, but seems the cleanest
161  // solution for now, as this call is
162  // once per event.
163  m_rngWrapper->setSeed("BEAMINT", ctx.slot(), event, run, ctx.evt());
164  CLHEP::HepRandomEngine* rndmEngine = m_rngWrapper->getEngine(ctx);
165  // m_biRandom->shoot() returns in range [0,1]
166  m_t0Offset = static_cast<unsigned int>(
167  floor((m_biRandom->shoot(rndmEngine) * m_ipLength) + 0.5));
168  } else {
169  FastReseededPRNG prng{m_seed.value(), run, event};
170  m_t0Offset = (*m_t0Dist)(prng);
171  }
172  assert(m_intensityPattern[m_t0Offset % m_ipLength] > 0.0); // just in case
173  ATH_MSG_DEBUG("selectT0 offset for this event " << m_t0Offset);
174  return;
175 }
176 
177 float ArrayBM::normFactor(int iXing) const
178 {
179  unsigned int index = static_cast<unsigned int>((((iXing + static_cast<int>(m_t0Offset)) % static_cast<int>(m_ipLength)) + static_cast<int>(m_ipLength) ) % static_cast<int>(m_ipLength));
180  //The array itself has max-value 1.0, but we want it to have mean value 1.0 (for filled bunch crossings), so we multiple by the m_largestElementInPattern.
181  ATH_MSG_VERBOSE("normFactor for BCID " << iXing
182  << " (offset " << m_t0Offset
183  << " index " << index
186 }
ArrayBM::initialize
virtual StatusCode initialize() override final
Definition: ArrayBM.cxx:45
FastReseededPRNG.h
ArrayBM::m_seed
Gaudi::Property< std::uint64_t > m_seed
seed for FastReseededPRNG. Non-zero switches to using FastReseededPRNG.
Definition: ArrayBM.h:59
index
Definition: index.py:1
ArrayBM::m_maxBunchCrossingPerOrbit
unsigned int m_maxBunchCrossingPerOrbit
max bunch crossings per orbit
Definition: ArrayBM.h:55
accumulate
bool accumulate(AccumulateMap &map, std::vector< module_t > const &modules, FPGATrackSimMatrixAccumulator const &acc)
Accumulates an accumulator (e.g.
Definition: FPGATrackSimMatrixAccumulator.cxx:22
CSV_InDetExporter.new
new
Definition: CSV_InDetExporter.py:145
ArrayBM::m_t0Offset
Gaudi::Hive::ContextSpecificData< unsigned int > m_t0Offset
offset of the t0 wrto our intensity pattern
Definition: ArrayBM.h:57
run
int run(int argc, char *argv[])
Definition: ttree2hdf5.cxx:28
ArrayBM.h
A IBeamIntensity service configured with an intensity array The Gaudi::Property<std::vector<float>> d...
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
Trk::u
@ u
Enums for curvilinear frames.
Definition: ParamDefs.h:83
ArrayBM::m_emptyBunches
int m_emptyBunches
Empty bunch option.
Definition: ArrayBM.h:82
ArrayBM::m_signalPattern
double * m_signalPattern
Additional array for keeping the locations we want signal in By default, will match the intensity pat...
Definition: ArrayBM.h:85
UtilityFuncs.h
prototypes for utility POOL collection funcs
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
event
POOL::TEvent event(POOL::TEvent::kClassAccess)
lumiFormat.i
int i
Definition: lumiFormat.py:92
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
run
Definition: run.py:1
Handler::svc
AthROOTErrorHandlerSvc * svc
Definition: AthROOTErrorHandlerSvc.cxx:10
xAOD::double
double
Definition: CompositeParticle_v1.cxx:159
ReadTripsProbsFromCool.denominator
denominator
Definition: ReadTripsProbsFromCool.py:96
ArrayBM::m_intensityPatternProp
Gaudi::Property< std::vector< float > > m_intensityPatternProp
user-defined intensity pattern
Definition: ArrayBM.h:61
ArrayBM::m_randomSvc
ServiceHandle< IAthRNGSvc > m_randomSvc
the service managing our random seeds/sequences
Definition: ArrayBM.h:71
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
ArrayBM::m_t0Dist
std::unique_ptr< const boost::random::discrete_distribution< unsigned int > > m_t0Dist
as with m_biRandom, but for FastReseededPRNG
Definition: ArrayBM.h:69
ArrayBM::m_ipLength
unsigned int m_ipLength
length of the intensity pattern
Definition: ArrayBM.h:63
RNGWrapper.h
ArrayBM::m_largestElementInPattern
float m_largestElementInPattern
The largest value in the pattern assuming that the pattern has mean value 1.0.
Definition: ArrayBM.h:77
ArrayBM::normFactor
virtual float normFactor(int iXing) const override final
Definition: ArrayBM.cxx:177
DeMoScan.index
string index
Definition: DeMoScan.py:362
ArrayBM::ArrayBM
ArrayBM(const std::string &name, ISvcLocator *svc)
Definition: ArrayBM.cxx:20
ArrayBM::m_intensityPattern
double * m_intensityPattern
normalized intensity pattern. C array to make clhep RandGeneral happy
Definition: ArrayBM.h:65
declareProperty
#define declareProperty(n, p, h)
Definition: BaseFakeBkgTool.cxx:15
ArrayBM::selectT0
virtual void selectT0(unsigned int run, unsigned long long event) override final
Definition: ArrayBM.cxx:155
ArrayBM::m_biRandom
CLHEP::RandGeneral * m_biRandom
shoot random number proportionally to m_intensityPattern
Definition: ArrayBM.h:67
ArrayBM::~ArrayBM
virtual ~ArrayBM()
Definition: ArrayBM.cxx:39
FastReseededPRNG
Definition: FastReseededPRNG.h:28