ATLAS Offline Software
xAODChargedTracksWeightFilter.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3  */
4 
8 #include "CLHEP/Random/RandomEngine.h"
9 #include <algorithm>
10 
12 
13 xAODChargedTracksWeightFilter::xAODChargedTracksWeightFilter(const std::string& name, ISvcLocator* pSvcLocator)
14  : GenFilter(name, pSvcLocator)
15 {
16  declareProperty("Ptcut", m_Ptmin = 50.0);
17  declareProperty("Etacut", m_EtaRange = 2.5);
18  declareProperty("NchMin", m_nchmin = 0);
19  declareProperty("NchMax", m_nchmax = 20);
20  declareProperty("SplineX", m_weight_fun_x);
21  declareProperty("SplineY", m_weight_fun_y);
22 }
23 
25 
26  CHECK(m_rndmSvc.retrieve());
27 
28  if(m_nchmin < 0) m_nchmin = 0;
29 
30  if(m_nchmax < m_nchmin || m_nchmin < 0) {
31  ATH_MSG_ERROR("Wrong values of NchMin and NchMax");
32  return StatusCode::FAILURE;
33  }
34 
36 
38 
39  for(int i=m_nchmin; i<=m_nchmax; i++){
40  ATH_MSG_DEBUG("nch = " << i
41  << " f(nch) = " << m_spline.value(i)
42  << " weight(nch) = " << get_nch_weight(i));
43  }
44 
45  if(m_min_weight<=0) {
46  ATH_MSG_ERROR("Weight functions must be >0");
47  return StatusCode::FAILURE;
48  }
49 
50  ATH_MSG_INFO(name() << " Minimum weight = " << m_min_weight);
51  return StatusCode::SUCCESS;
52 }
53 
55 
57  ATH_MSG_INFO(name() << " Weight-Filtering Only Efficiency = " << eff
58  << " [" << m_nevents_accepted << " / " << m_nevents_selected << "] \n");
59 
60  return StatusCode::SUCCESS;
61 }
62 
63 CLHEP::HepRandomEngine* xAODChargedTracksWeightFilter::getRandomEngine(const std::string& streamName,
64  const EventContext& ctx) const
65 {
66  ATHRNG::RNGWrapper* rngWrapper = m_rndmSvc->getEngine(this, streamName);
67  std::string rngName = name()+streamName;
68  rngWrapper->setSeed( rngName, ctx );
69  return rngWrapper->getEngine(ctx);
70 }
71 
72 
74 
75  // Retrieve TruthGen container from xAOD Gen slimmer, contains all particles witout barcode_zero and
76 // duplicated barcode ones
77  const xAOD::TruthParticleContainer* xTruthParticleContainer;
78  if (evtStore()->retrieve(xTruthParticleContainer, "TruthGen").isFailure()) {
79  ATH_MSG_ERROR("No TruthParticle collection with name " << "TruthGen" << " found in StoreGate!");
80  return StatusCode::FAILURE;
81  }
82 
83  const EventContext& ctx = Gaudi::Hive::currentContext();
84  CLHEP::HepRandomEngine* rndmGen = this->getRandomEngine(name(), ctx);
85  if (!rndmGen) {
86  ATH_MSG_WARNING("Failed to retrieve random number engine " << name());
87  setFilterPassed(false);
88  return StatusCode::FAILURE;
89  }
90 
91  int nChargedTracks = 0;
92  unsigned int nPart = xTruthParticleContainer->size();
93  for (unsigned int iPart = 0; iPart < nPart; ++iPart) {
94  const xAOD::TruthParticle* part = (*xTruthParticleContainer)[iPart];
95 
96  // We only care about stable particles
97  if (!part->isGenStable()) continue;
98 
99  // Particle's charge
100  int pID = part->pdgId();
101  double pCharge = MC::charge(pID);
102 
103  // Count tracks in specified acceptance
104  const double pT = part->pt();
105  const double eta = part->eta();
106  if (pT >= m_Ptmin && std::abs(eta) <= m_EtaRange && pCharge != 0) {
107  ATH_MSG_DEBUG("Found particle, " <<
108  " pT = " << pT <<
109  " eta = " << eta <<
110  " pdg id = " << pID <<
111  " charge = " << pCharge << " in acceptance");
112  nChargedTracks += 1;
113  }
114 
115  } // end of particles loop
116 
117  // Summarise event
118  ATH_MSG_DEBUG("# of tracks " << nChargedTracks <<
119  " with pT >= " << m_Ptmin <<
120  " |eta| < " << m_EtaRange <<
121  " nch_min= " << m_nchmin<<
122  " nch_max= " << m_nchmax);
123 
124  // get event weight from the McEventCollection, used to determine efficiency of weight-filtering and cuts
125  double orig_event_weight = 1;
126  CHECK(event_weight(orig_event_weight));
127 
128  const auto selection = (((nChargedTracks <= m_nchmax)) && (nChargedTracks >= m_nchmin));
129 
130 
131  if(!selection) {
132  setFilterPassed(false);
133  return StatusCode::SUCCESS;
134  }
135 
136  m_nevents_selected += orig_event_weight;
137 
138  // weight-filtering weight
139  const auto weight = get_nch_weight(nChargedTracks);
140 
141  bool accept = false;
142 
143  if(weight >=1){
144  accept = true;
145  } else {
146  // weighting
147  double rnd = rndmGen->flat();
148  if(weight>rnd) {
149  accept = true;
150  }
151  }
152 
153  if(accept) {
154 
156 
157  setFilterPassed(true);
158 
159  double final_event_weight = 1;
160  CHECK(event_weight(final_event_weight));
161 
162  ATH_MSG_DEBUG("Event accepted nch: " << nChargedTracks
163  << " nch weight: " << weight
164  << " orig_event_weight: " << orig_event_weight
165  << " new_event_weight: " << final_event_weight);
166  m_nevents_accepted += orig_event_weight;
167  return StatusCode::SUCCESS;
168  }
169 
170  setFilterPassed(false);
171  return StatusCode::SUCCESS;
172 }
173 
175 
176  // interval with no weighting
177  if( nch > m_nchmax || nch < m_nchmin ) return 1;
178 
179  auto w_fc = m_spline.value(nch);
180 
181  return m_min_weight/w_fc;
182 }
183 
184 
186 
187  for (auto event : *(events())){
188  if(!event) continue;
189 
190  if (event->weights().empty()) {
191  event->weights().push_back( 1/weight );
192  } else {
193  for (auto & w: event-> weights()) {
194  w /= weight;
195  }
196 
197 #ifdef HEPMC3
198  event->add_attribute("filterWeight", std::make_shared<HepMC3::DoubleAttribute>(1/weight));
199 #endif
200  }
201 
202  }
203 }
204 
206 // spline
208 
209 bool comp_x (const Point & lhs, const Point &rhs){
210  return lhs.x < rhs.x;
211 }
212 
213 bool comp_y (const Point & lhs, const Point &rhs){
214  return lhs.y < rhs.y;
215 }
216 
218 
219  const double dummy = -1;
220 
221  // find lowest weight in allowed range
222  auto lower = std::upper_bound(points.begin(), points.end(),
223  Point(nch, dummy, dummy), comp_x);
224 
225  if(lower != points.begin()) lower--;
226 
227  const auto & x = lower-> x;
228  const auto & y = lower-> y;;
229  const auto & slope = lower-> slope;;
230 
231  // weight using linear spline
232  const auto w_fc = (nch-x)*slope + y;
233 
234  if(w_fc<0) return 0; // extrapolation gives negative value
235  else return w_fc;
236 }
237 
239  // evaluate minimum of the spline over a defined range
240 
241  // spline must be initialized
242  if(points.empty()) return -1;
243 
244  const double dummy = -1;
245 
246  // if min, max are in between points, or extrapolation needed
247  auto minimum = std::min(value(min), value(max));
248 
249  // find boundary points and scan the allowed range
250  auto min_item = std::lower_bound(points.begin(), points.end(), Point(min, dummy, dummy), comp_x);
251  auto max_item = std::upper_bound(points.begin(), points.end(), Point(max, dummy, dummy), comp_x);
252 
253  if(min_item != max_item) {
254  const auto smallest = std::min_element(min_item, max_item, comp_y);
255  minimum = std::min(minimum, smallest-> y);
256  }
257 
258  return minimum;
259 }
260 
261 StatusCode xAODChargedTracksWeightFilter::Spline::initialize( std::vector<double> & x, std::vector<double> & y) {
262 
263  if(x.size() < 2 || x.size() != y.size()) {
264  std::cout << "Spline not properly defined. SplineX, SplineY vectors are required to have at least 2 elements and same size.\n";
265  return StatusCode::FAILURE;
266  }
267 
268  // calculate slope terms
269  for(size_t i=0; i< x.size()-1; i++){
270 
271  const auto & x0 = x[i];
272  const auto & y0 = y[i];
273  const auto & x1 = x[i+1];
274  const auto & y1 = y[i+1];
275 
276  const auto dx = x1 - x0;
277  const auto dy = y1 - y0;
278 
279  if(dx <=0) {
280  std::cout << "Spline not properly defined. SplineX is required to be monotonically increasing.\n";
281  return StatusCode::FAILURE;
282  }
283 
284  points.push_back( Point(x[i], y[i], dy/dx));
285  }
286 
287  return StatusCode::SUCCESS;
288 }
289 
291 
292  event_weight = 1;
293 
294  auto first_event = event_const();
295 
296  if(!first_event){
297  ATH_MSG_ERROR("No events in McEventCollection");
298  return StatusCode::FAILURE;
299  }
300 
301  if(! first_event-> weights().empty()) {
302  event_weight = first_event-> weights()[0];
303  }
304 
305  return StatusCode::SUCCESS;
306 }
LArG4FSStartPointFilter.part
part
Definition: LArG4FSStartPointFilter.py:21
python.PyKernel.retrieve
def retrieve(aClass, aKey=None)
Definition: PyKernel.py:110
ATHRNG::RNGWrapper::setSeed
void setSeed(const std::string &algName, const EventContext &ctx)
Set the random seed using a string (e.g.
Definition: RNGWrapper.h:169
plotBeamSpotCompare.x1
x1
Definition: plotBeamSpotCompare.py:216
CalculateHighPtTerm.pT
pT
Definition: ICHEP2016/CalculateHighPtTerm.py:57
xAODChargedTracksWeightFilter::Spline::initialize
StatusCode initialize(std::vector< double > &x, std::vector< double > &y)
Definition: xAODChargedTracksWeightFilter.cxx:261
max
#define max(a, b)
Definition: cfImp.cxx:41
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
eta
Scalar eta() const
pseudorapidity method
Definition: AmgMatrixBasePlugin.h:79
AthCommonDataStore< AthCommonMsg< Algorithm > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T > &t)
Definition: AthCommonDataStore.h:145
ChargedTracksWeightFilter::Spline::Point::y
double y
Definition: ChargedTracksWeightFilter.h:34
xAODChargedTracksWeightFilter::m_min_weight
double m_min_weight
Definition: xAODChargedTracksWeightFilter.h:88
xAODChargedTracksWeightFilter::event_weight
StatusCode event_weight(double &event_weight) const
read the event weight
Definition: xAODChargedTracksWeightFilter.cxx:290
xAODChargedTracksWeightFilter::m_nchmin
int m_nchmin
Definition: xAODChargedTracksWeightFilter.h:77
xAODChargedTracksWeightFilter::m_weight_fun_x
std::vector< double > m_weight_fun_x
Spline points.
Definition: xAODChargedTracksWeightFilter.h:85
CutsMETMaker::accept
StatusCode accept(const xAOD::Muon *mu)
Definition: CutsMETMaker.cxx:18
xAODChargedTracksWeightFilter::Spline::value
double value(int nch) const
get value for certain x
Definition: xAODChargedTracksWeightFilter.cxx:217
xAODChargedTracksWeightFilter::xAODChargedTracksWeightFilter
xAODChargedTracksWeightFilter(const std::string &name, ISvcLocator *pSvcLocator)
Definition: xAODChargedTracksWeightFilter.cxx:13
xAODChargedTracksWeightFilter::m_nevents_selected
double m_nevents_selected
Number of events passing selection (weighted, orig weight)
Definition: xAODChargedTracksWeightFilter.h:91
xAODChargedTracksWeightFilter::Spline::points
std::vector< Point > points
n-1 spline points filled at initialization
Definition: xAODChargedTracksWeightFilter.h:42
athena.value
value
Definition: athena.py:122
xAODChargedTracksWeightFilter::m_spline
Spline m_spline
Definition: xAODChargedTracksWeightFilter.h:82
comp_y
bool comp_y(const Point &lhs, const Point &rhs)
Definition: xAODChargedTracksWeightFilter.cxx:213
xAODChargedTracksWeightFilter::m_nevents_accepted
double m_nevents_accepted
Number of events passing weight-filtering (weighted, origin weight)
Definition: xAODChargedTracksWeightFilter.h:93
xAODChargedTracksWeightFilter::Spline::Point
Linear spline representation of a function used to calculate weights.
Definition: xAODChargedTracksWeightFilter.h:31
x
#define x
empty
bool empty(TH1 *h)
Definition: computils.cxx:294
python.DataFormatRates.events
events
Definition: DataFormatRates.py:105
makeTRTBarrelCans.y1
tuple y1
Definition: makeTRTBarrelCans.py:15
dqt_zlumi_pandas.weight
int weight
Definition: dqt_zlumi_pandas.py:200
xAODChargedTracksWeightFilter::m_Ptmin
double m_Ptmin
Definition: xAODChargedTracksWeightFilter.h:71
xAODChargedTracksWeightFilter::filterEvent
StatusCode filterEvent()
Definition: xAODChargedTracksWeightFilter.cxx:73
AthCommonDataStore< AthCommonMsg< Algorithm > >::evtStore
ServiceHandle< StoreGateSvc > & evtStore()
The standard StoreGateSvc (event store) Returns (kind of) a pointer to the StoreGateSvc.
Definition: AthCommonDataStore.h:85
xAODChargedTracksWeightFilter::get_nch_weight
double get_nch_weight(int nch) const
get weight to filter and weight events
Definition: xAODChargedTracksWeightFilter.cxx:174
GenFilter
Base class for event generator filtering modules.
Definition: GenFilter.h:30
xAODChargedTracksWeightFilter::m_weight_fun_y
std::vector< double > m_weight_fun_y
Definition: xAODChargedTracksWeightFilter.h:86
xAODChargedTracksWeightFilter::filterInitialize
StatusCode filterInitialize()
Definition: xAODChargedTracksWeightFilter.cxx:24
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
xAOD::TruthParticle_v1
Class describing a truth particle in the MC record.
Definition: TruthParticle_v1.h:41
xAODChargedTracksWeightFilter::weight_event
void weight_event(double weight)
modify the event weight by weight
Definition: xAODChargedTracksWeightFilter.cxx:185
xAOD::TauJetParameters::nChargedTracks
@ nChargedTracks
Definition: TauDefs.h:322
xAODChargedTracksWeightFilter::m_nchmax
int m_nchmax
Definition: xAODChargedTracksWeightFilter.h:80
python.xAODType.dummy
dummy
Definition: xAODType.py:4
CHECK
#define CHECK(...)
Evaluate an expression and check for errors.
Definition: Control/AthenaKernel/AthenaKernel/errorcheck.h:422
ChargedTracksWeightFilter::Spline::Point::x
double x
Definition: ChargedTracksWeightFilter.h:31
selection
std::string selection
Definition: fbtTestBasics.cxx:73
DataVector
Derived DataVector<T>.
Definition: DataVector.h:581
min
#define min(a, b)
Definition: cfImp.cxx:40
xAODChargedTracksWeightFilter::m_EtaRange
double m_EtaRange
Definition: xAODChargedTracksWeightFilter.h:74
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
xAODChargedTracksWeightFilter::Spline::get_minimum
double get_minimum(double min, double max) const
get minimum over certain range (requires initialization to extrapolate)
Definition: xAODChargedTracksWeightFilter.cxx:238
ATHRNG::RNGWrapper
A wrapper class for event-slot-local random engines.
Definition: RNGWrapper.h:56
ChargedTracksWeightFilter::Spline::Point
Linear spline representation of a function used to calculate weights.
Definition: ChargedTracksWeightFilter.h:28
charge
double charge(const T &p)
Definition: AtlasPID.h:494
Point
xAODChargedTracksWeightFilter::Spline::Point Point
Definition: xAODChargedTracksWeightFilter.cxx:11
xAODChargedTracksWeightFilter::m_rndmSvc
ServiceHandle< IAthRNGSvc > m_rndmSvc
Rndm generator service.
Definition: xAODChargedTracksWeightFilter.h:68
ATHRNG::RNGWrapper::getEngine
CLHEP::HepRandomEngine * getEngine(const EventContext &ctx) const
Retrieve the random engine corresponding to the provided EventContext.
Definition: RNGWrapper.h:134
RNGWrapper.h
makeTRTBarrelCans.dy
tuple dy
Definition: makeTRTBarrelCans.py:21
AthenaPoolExample_Copy.streamName
string streamName
Definition: AthenaPoolExample_Copy.py:39
y
#define y
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
xAODChargedTracksWeightFilter::filterFinalize
StatusCode filterFinalize()
Definition: xAODChargedTracksWeightFilter.cxx:54
xAODChargedTracksWeightFilter::getRandomEngine
CLHEP::HepRandomEngine * getRandomEngine(const std::string &streamName, const EventContext &ctx) const
Definition: xAODChargedTracksWeightFilter.cxx:63
makeTRTBarrelCans.dx
tuple dx
Definition: makeTRTBarrelCans.py:20
comp_x
bool comp_x(const Point &lhs, const Point &rhs)
Definition: xAODChargedTracksWeightFilter.cxx:209
dqt_zlumi_alleff_HIST.eff
int eff
Definition: dqt_zlumi_alleff_HIST.py:113
python.IoTestsLib.w
def w
Definition: IoTestsLib.py:200
DataVector::size
size_type size() const noexcept
Returns the number of elements in the collection.
xAODChargedTracksWeightFilter.h
GenBase::event_const
const HepMC::GenEvent * event_const() const
Access the current signal event (const)
Definition: GenBase.h:83
HepMCHelpers.h