#ifndef __JAANET_JMULTIHEAD__ #define __JAANET_JMULTIHEAD__ #include #include #include #include "km3net-dataformat/offline/Evt.hh" #include "km3net-dataformat/offline/Head.hh" #include "km3net-dataformat/offline/MultiHead.hh" #include "JLang/JUUID.hh" #include "JLang/JException.hh" #include "JAAnet/JHead.hh" #include "JAAnet/JEvtWeightHelper.hh" #include "JAAnet/JEvtWeightToolkit.hh" #include "JAAnet/JEvtWeightSupportkit.hh" /** * \author bjjung */ namespace JAANET {} namespace JPP { using namespace JAANET; } namespace JAANET { using JLANG::JUUID; /** * Auxiliary data structure to store multiple headers\n * and bookkeep event-weight normalisations. */ struct JMultiHead : public MultiHead { typedef std::map map_type; /** * Default constructor. */ JMultiHead() : MultiHead() {} /** * Merge the given header into this object. * * \param header header */ void merge(const JHead& header) { insert(header); merge(); } /** * Insert the given header. * * \param header header * \return true if insertion was successful; else false */ bool insert(const JHead& header) { using namespace std; Head head; JAANET::copy(header, head); uuid_t uuid; uuid_clear(uuid); Head::iterator i = head.find(Head::tags::UUID); if (i != head.end()) { uuid_parse(i->second.c_str(), uuid); } if (uuid_is_null(uuid) != 0) { uuid_generate_random(uuid); // Ensure valid UUID } char buffer[JUUID::BUFFER_SIZE + 1]; uuid_unparse_lower(uuid, buffer); head.insert(make_pair(Head::tags::UUID, buffer)); return MultiHead::insert(head); } /** * Check if given header UUID correspond to a file which has been merged. * * \param UUID header UUID * \return true if given header UUID correspond to file which has been merged */ bool isMerged(const JUUID& UUID) const { using namespace JPP; map_type::const_iterator i = normalisationMap.find(UUID); if (i != normalisationMap.end()) { return i->first != i->second.UUID; } else { THROW(JValueOutOfRange, "JMultiHead::isMerged(): Given header UUID " << UUID << " not found."); } } /** * Get the header UUID corresponding to the given event. * * \param event event * \return header UUID */ JUUID getHeaderUUID(const Evt& event) const { using namespace JPP; const JUUID UUID = event.header_uuid; map_type::const_iterator i = normalisationMap.find(UUID); if (i != normalisationMap.cend()) { return i->second.UUID; } else { THROW(JValueOutOfRange, "JMultiHead::getHeaderUUID(): Header UUID " << UUID << " for given event not found."); } } /** * Get normalisation for given header UUID. * * \param UUID header UUID * \return event-weight normalisation factor */ double getNormalisation(const JUUID& UUID) const { using namespace JPP; map_type::const_iterator i = normalisationMap.find(UUID); if (i != normalisationMap.end()) { return i->second.normalisation; } else { THROW(JValueOutOfRange, "JMultiHead::getNormalisation(): Given header UUID " << UUID << " not found."); } } /** * Get normalisation for given event. * * \param event event * \return event-weight normalisation factor */ double getNormalisation(const Evt& event) const { return getNormalisation(event.header_uuid); } /** * Merge all matching headers. */ void merge() { using namespace std; using namespace JPP; const MultiHead copy = static_cast(*this); this->clear(); for (const_iterator i = copy.cbegin(); i != copy.cend(); ++i) { JHead header1 = *i; header1.createUUID(); // Ensure header UUID is set const JUUID UUID = header1.UUID; // Initial header UUID // Merge matching headers following this header in the container vector mergedHeaders; // Track all headers involved in mergers for (const_iterator j = next(i); j != copy.end(); ++j) { const JHead header2 = *j; if (header1.match(header2)) { header1.add(header2); mergedHeaders.push_back(header2.UUID); } } // Retrieve event-weight normalisation for merged header const JEvtWeight& weighter = getEventWeighter(header1); JEvtWeightHelper helper(weighter); helper.add(header1); const double norm = helper->getNormalisation(); // Set event-weight normalisations for headers involved in mergers for (vector::const_iterator j = mergedHeaders.cbegin(); j != mergedHeaders.cend(); ++j) { normalisationMap[*j] = JEvtWeightNormalisation(header1.UUID, norm); } // Set event-weight normalisation for original header normalisationMap[UUID] = JEvtWeightNormalisation(header1.UUID, norm); insert(header1); // Add merged header to buffer } } map_type normalisationMap; //!< Map between header UUIDs and event-weight normalisations }; } #endif