ATLAS Offline Software
Loading...
Searching...
No Matches
HepMCWeightSvc.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3*/
4
5
6#include "HepMCWeightSvc.h"
8#include "CoralBase/AttributeListException.h"
12#include <regex>
13
14
19{
20 ATH_CHECK( m_eventInfoKey.initialize() );
21 return StatusCode::SUCCESS;
22}
23
24
32StatusCode
34 const EventContext& ctx /*= Gaudi::Hive::currentContext()*/)
35{
36 std::scoped_lock lock (m_mutex);
37
38 // Ignore any attempt to set 'nothing' for the weight names.
39 if (weightNames.size()==0 ||
40 (weightNames.size()==1 && weightNames.begin()->first=="0") )
41 {
42 return StatusCode::SUCCESS;
43 }
44
45 if (m_weights[0].m_chanNum != 0 || m_nextWeight != 0) {
46 // We only allow setting of weightNames ONCE! ...
47 // if the weights have ever been loaded, we will not allow
48 // them to be set again!
49 // Effectively means the weights are only set in evgen jobs.
50 return StatusCode::SUCCESS;
51 }
52
53 unsigned int chanNum = ctx.eventID().run_number();
54
56 w.m_chanNum = chanNum;
57 w.m_weightNames = weightNames;
58 w.fillVec();
59
60 // Create and register the metadata containter with these weight names
61 // Use the MetaDataTool to do this
62 ATH_CHECK( m_metaDataTool->registerFolder("/Generation/Parameters","Metadata created during Event Generation") );
63
64 // Create a new attributelist collection for it ...
65 auto cont = std::make_unique<CondAttrListCollection> (true /* use regular timestamps, not run-lumiblock timestamps */) ;
66
67 // Create a single attribute list.
69
70 // Store as strings ... when read back in we use a gaudi parser to parse the list
71 myAttributes.extend("HepMCWeightNames","string");
72 myAttributes.extend("HepMCWeightSvcVersion","int");
73 myAttributes["HepMCWeightSvcVersion"].data<int>() = 2;
74
75 std::string stringToStore = Gaudi::Utils::toString( weightNames );
76
77 myAttributes["HepMCWeightNames"].data<std::string>() = stringToStore;
78
79 // Use the run-number as the 'channel' ... all weightnames should be the same for the same channel
80 bool add_status = cont->add(chanNum, myAttributes);
81 if (!add_status) {
82 ATH_MSG_INFO("Failed to add AttributeList for weight " << stringToStore);
83 }
84
85 ATH_MSG_INFO("Storing /Generation/Parameters :: WeightNames = " << stringToStore);
86
87 // And assign it to 'channel 0' .. consistent with other metadata
88 ATH_CHECK( m_metaDataTool->addPayload("/Generation/Parameters", cont.release()) );
89
90 return StatusCode::SUCCESS;
91}
92
93
97HepMCWeightSvc::WeightMap
98HepMCWeightSvc::weightNames (const EventContext& ctx /*= Gaudi::Hive::currentContext()*/)
99{
100 std::scoped_lock lock (m_mutex);
101 size_t i = getWeightIndex (ctx);
102 if (i < NWEIGHTS) {
103 return m_weights[i].m_weightNames;
104 }
105
106 ATH_MSG_WARNING("Unable to load weightnames from metadata ... do not trust the weightnames!");
107 return WeightMap();
108}
109
110
114std::vector<std::string>
115HepMCWeightSvc::weightNameVec (const EventContext& ctx /*= Gaudi::Hive::currentContext()*/)
116{
117 std::scoped_lock lock (m_mutex);
118 size_t i = getWeightIndex (ctx);
119 if (i < NWEIGHTS) {
120 return m_weights[i].m_weightNameVec;
121 }
122
123 ATH_MSG_WARNING("Unable to load weightnames from metadata ... do not trust the weightnames!");
124 return std::vector<std::string>();
125}
126
127
134unsigned long HepMCWeightSvc::getChanNum (const EventContext& ctx) const
135{
136 // Try first to get the MC channel number from EventInfo.
138 if (ei.isValid()) {
139 unsigned long chanNum = ei->mcChannelNumber();
140 if (chanNum > 0) return chanNum;
141 }
142 // Fall back to run number.
143 return ctx.eventID().run_number();
144}
145
146
153unsigned int HepMCWeightSvc::loadWeights (unsigned long chanNum)
154{
155 // Must be called holding the service mutex.
156
157 if (!m_enabled) return NWEIGHTS;
158
159 std::map<std::string, int> in;
160
162 const IOVMetaDataContainer* cont = m_metaDataTool->findMetaDataContainer ("/Generation/Parameters");
163
164 // Return quietly if container isn't there.
165 if (cont) {
166 if (cont->payloadContainer()->size() == 0) return NWEIGHTS;
167
168 unsigned long chanNumRead = chanNum;
169 // If there is only one collection of weights, then we just load that one.
170 if (cont->payloadContainer()->at(0)->size()==1) {
171 chanNumRead = cont->payloadContainer()->at(0)->chanNum(0);
172 }
173
174 const coral::Attribute& attr = cont->payloadContainer()->at(0)->attributeList(chanNumRead)["HepMCWeightNames"];
175
176 int version = 1;
177 try {
178 version = cont->payloadContainer()->at(0)->attributeList(chanNumRead)["HepMCWeightSvcVersion"].data<int>();
179 } catch(const coral::AttributeListException&) {
180 version = 1; //no version available so assume version 1
181 }
182
183 std::string weightNames = attr.data<std::string>();
184
185 //protect against malformed weightnames - see ATLMCPROD-3103
186 //this actually only came about because the Gaudi::Utils::toString method was not used
187 //in setWeightNames below. I've now corrected that, but now the fear is that these
188 //replacements will interfere with those too!
189 //so use a versioning system now
190 if(version==1) {
191 weightNames = std::regex_replace(weightNames, std::regex(R"(\{')"), "{\"");
192 weightNames = std::regex_replace(weightNames, std::regex(R"(':)"), "\":");
193 weightNames = std::regex_replace(weightNames, std::regex(R"(, ')"), ", \"");
194 }
195
196 ATH_MSG_DEBUG("Loading weightnames: " << weightNames);
197
198 if( Gaudi::Parsers::parse(in,weightNames).isFailure() ) return NWEIGHTS;
199 }
200
201 size_t iweight = m_nextWeight;
202 if (++m_nextWeight >= NWEIGHTS) {
203 m_nextWeight = 0;
204 }
205
206 WeightInfo& w = m_weights[iweight];
207 w.m_chanNum = chanNum;
208 w.m_weightNames.clear();
209
210 for(const auto& i : in) {
211 w.m_weightNames[i.first] = i.second;
212 }
213 w.fillVec();
214
215 return iweight;
216}
217
218
225unsigned int HepMCWeightSvc::getWeightIndex (const EventContext& ctx)
226{
227 unsigned long chanNum = getChanNum (ctx);
228 if (chanNum != 0) {
229 for (size_t i = 0; i < NWEIGHTS; i++) {
230 if (m_weights[i].m_chanNum == chanNum) {
231 return i;
232 }
233 }
234 return loadWeights (chanNum);
235 }
236 return NWEIGHTS;
237}
238
239
244{
245 m_weightNameVec.clear();
246 using WPair = std::pair<std::string, unsigned long int>;
247 std::vector<WPair> sorted;
248 for(const auto& i : m_weightNames) {
249 sorted.emplace_back (i);
250 }
251 std::sort (sorted.begin(), sorted.end(),
252 [](const WPair& a, const WPair& b) {return a.second < b.second; });
253 for (auto& a: sorted) {
254 m_weightNameVec.emplace_back (std::move (a.first));
255 }
256}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_INFO(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
This file defines the class for a collection of AttributeLists where each one is associated with a ch...
This class is a container for conditions data.
static Double_t a
Handle class for reading from StoreGate.
RAII helper for acquiring the lock of an ILockableTool.
const AttributeList & attributeList(ChanNum chanNum) const
attribute list for a given channel number
ChanNum chanNum(unsigned int index) const
channel number for index: (index = 0 to size-1)
size_type size() const
number of Chan/AttributeList pairs
coral::AttributeList AttributeList
virtual StatusCode initialize() override
Standard Gaudi initialize.
static const unsigned int NWEIGHTS
Array of weights.
WeightInfo m_weights[NWEIGHTS]
unsigned long getChanNum(const EventContext &ctx) const
Return the ‘channel number’ for the current event.
virtual StatusCode setWeightNames(const WeightMap &weightNames, const EventContext &ctx=Gaudi::Hive::currentContext()) override
Record weight names to metadata if none have yet been set.
Gaudi::Property< bool > m_enabled
unsigned int loadWeights(unsigned long chanNum)
Try to load weight names from metadata.
size_t m_nextWeight
Index of next set of weights to overwrite.
virtual std::vector< std::string > weightNameVec(const EventContext &ctx=Gaudi::Hive::currentContext()) override
Return the current weight names.
unsigned int getWeightIndex(const EventContext &ctx)
Return the index in m_weights for the current event.
SG::ReadHandleKey< xAOD::EventInfo > m_eventInfoKey
Used to get MC channel for the current event.
virtual WeightMap weightNames(const EventContext &ctx=Gaudi::Hive::currentContext()) override
Return the current weight names.
std::mutex m_mutex
Serialize access to this service.
PublicToolHandle< IIOVDbMetaDataTool > m_metaDataTool
Handle to metadata tool.
This class is a container for conditions data.
const IOVPayloadContainer * payloadContainer() const
Access to payload container.
size_type size() const
size of payload vector
CondAttrListCollection * at(unsigned int i) const
Element access.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
StatusCode parse(std::tuple< Tup... > &tup, const Gaudi::Parsers::InputData &input)
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
Cached sets of weights.
WeightMap m_weightNames
Map of weight names.
void fillVec()
Initialize sorted vector from map.
std::vector< std::string > m_weightNameVec
Sorted vector of weight names.