16 template <
unsigned int N>
18 using In_t = Writer_t<1>::input_type;
19 using Consumer_t = Writer_t<1>::consumer_type;
22 template <
typename A=detail::defaultAccessor_t<Consumer_t>>
23 void addCustomType(Consumer_t& c,
29 throw std::logic_error(
"called addCustomType on non-custom type");
31 bool force_precision =
p.type == Primitive::Type::PRECISION_CUSTOM;
36 const std::string
s =
p.source;
37 const std::string
t =
p.target;
42 auto add = [&
c,
a,
t](
auto f,
auto compression,
float mult = 1.0) {
45 [
a, f, mult](
I in) ->
float {
46 const auto* associated =
a(in);
47 if (!associated)
return NAN;
48 return f(associated)*mult;
54 auto match = [&
add,
s, &
m, half](
const std::string&
n,
auto func) {
64 auto matchGeV = [&
add,
s, &
m, half](
const std::string&
n,
auto func) {
71 throw std::logic_error(
72 "asked for a full precision version of a variable that can"
73 " not be stored at half precision: " + s);
77 }
else if (s == n +
"GeV") {
78 add(func, half, 0.001);
84 matchGeV(
"pt", [](
auto in) {
return in->pt(); });
85 match(
"eta", [](
auto in) {
return in->eta(); });
86 match(
"phi", [](
auto in) {
return in->phi(); });
87 matchGeV(
"px", [](
auto in) {
return in->p4().Px(); });
88 matchGeV(
"py", [](
auto in) {
return in->p4().Py(); });
89 matchGeV(
"pz", [](
auto in) {
return in->p4().Pz(); });
90 matchGeV(
"mass", [](
auto in) {
return in->m(); });
95 c.add(s, [](
I) {
return true; },
false);
98 throw std::logic_error(
"unknow known custom primitive: " + s);
103 template <
typename T,
typename R=SG::AuxElement>
107 LinkGetter(std::string name);
108 const R* operator()(In_t in)
const;
111 const LinkAccessor m_accessor;
112 const std::string m_linkName;
114 template <
typename T,
typename R>
115 LinkGetter<T,R>::LinkGetter(std::string name):
119 template <
typename T,
typename R>
120 const R* LinkGetter<T,R>::operator()(In_t in)
const {
121 auto elink = m_accessor(*in);
127 if (elink.isDefault()) {
134 if (!elink.isValid()) {
135 throw std::runtime_error(
"invalid link " + m_linkName);
140 CountWriter_t::consumer_type getOffsetConsumer()
142 using CountIn_t = CountWriter_t::input_type;
143 CountWriter_t::consumer_type
c;
144 c.add(
"count", [](CountIn_t i) {
return i; });
157 virtual void fill(
const std::vector<const xAOD::IParticle*>& info) = 0;
166 Writer_t<1> m_writer;
168 IParticle2dWriter(H5::Group& group,
169 const std::string& n,
171 long long unsigned size):
172 m_writer(group, n, c, {{size}}) {}
173 ~IParticle2dWriter() =
default;
175 void fill(
const std::vector<In_t>& v)
override {
178 void flush()
override {
188 Writer_t<0> m_writer;
189 CountWriter_t m_counts;
191 IParticleAwkwardWriter(H5::Group& parent,
192 const std::string& n,
194 m_group(
parent.createGroup(
n)),
195 m_writer(m_group,
"raw",
c),
196 m_counts(m_group,
"counts", getOffsetConsumer())
198 ~IParticleAwkwardWriter() =
default;
200 void fill(
const std::vector<In_t>& v)
override {
201 using Count_t = CountWriter_t::input_type;
202 constexpr auto max = std::numeric_limits<Count_t>::max();
203 auto n_entries =
v.size();
204 if (n_entries >
max) {
205 throw std::overflow_error(
206 "number of entries exceeds maximum for this datatype "
207 "[" + std::to_string(n_entries) +
" > " + std::to_string(
max) +
"]"
210 for (
const auto& e: v) m_writer.fill(e);
211 m_counts.fill(n_entries);
213 void flush()
override {
225 Writer_t<0> m_writer;
227 IParticleFlatWriter(H5::Group& parent,
228 const std::string& n,
232 ~IParticleFlatWriter() =
default;
234 void fill(
const std::vector<In_t>& v)
override {
235 for (
const auto& e: v) m_writer.fill(e);
237 void flush()
override {
242 std::unique_ptr<details::IParticleWriterBase> getWriter(
247 switch (
cfg.format) {
249 if (
cfg.maximum_size != 0) {
250 throw std::domain_error(
251 "no maximum_size should be specified for awkward arrays");
253 return std::make_unique<IParticleAwkwardWriter>(g,
cfg.name, c);
256 if (
cfg.maximum_size != 0) {
257 throw std::domain_error(
258 "no maximum_size should be specified for flat arrays");
260 return std::make_unique<IParticleFlatWriter>(g,
cfg.name, c);
263 if (
cfg.maximum_size == 0) {
264 throw std::domain_error(
265 "maximum_size should be specified for padded 2d arrays");
267 return std::make_unique<IParticle2dWriter>(
268 g,
cfg.name, c,
cfg.maximum_size);
271 throw std::domain_error(
"unknown array format");
285 for (
const auto& input: cfg.inputs) {
286 if (input.link_name.empty()) {
287 const auto& primitive = input.input;
289 addCustomType(c, primitive);
295 std::string n = input.link_name;
297 if (n ==
"btaggingLink") {
298 LinkGetter<xAOD::BTaggingContainer> getter(n);
302 LinkGetter<IPC,IP> getter(n);
304 addCustomType(c, input.input, getter);
311 m_writer = getWriter(group, cfg, c);
void fill(const std::vector< const xAOD::IParticle * > &)
std::unique_ptr< details::IParticleWriterBase > m_writer
IParticleWriter(H5::Group &output_group, const IParticleWriterConfig &)
SG::ConstAccessor< T, ALLOC > ConstAccessor
virtual ~IParticleWriterBase()=default
virtual void fill(const std::vector< const xAOD::IParticle * > &info)=0
Class providing the definition of the 4-vector interface.
bool add(const std::string &hname, TKey *tobj)
bool match(std::string s1, std::string s2)
match the individual directories of two strings
double R(const INavigable4Momentum *p1, const double v_eta, const double v_phi)
void addInput(T &c, const Primitive &input, A a=defaultAccessor< T >)
bool isCustom(const Primitive &p)
DataVector< IParticle > IParticleContainer
Simple convenience declaration of IParticleContainer.
hold the test vectors and ease the comparison
void fill(H5::Group &out_file, size_t iterations)