#ifndef __JROOT__JDATAFRAME__ #define __JROOT__JDATAFRAME__ #include #include #include #include #include "TROOT.h" #include "TClass.h" #include "TDataMember.h" #include "ROOT/RDF/RInterfaceBase.hxx" #include "ROOT/RDataFrame.hxx" #include "JLang/JSingleton.hh" #include "JLang/JException.hh" #include "JTools/JRange.hh" /** * \author mdejong */ namespace JROOT {} namespace JPP { using namespace JROOT; } namespace JROOT { using JLANG::JSingleton; using JLANG::JException; /** * Auxiliary class for parsing data from ROOT data frame. */ class JDataFrame { public: /** * Type definition for range. */ typedef JTOOLS::JRange range_type; private: /** * Interface for output. */ struct JOutput { /** * Virtual destructor. */ virtual ~JOutput() {} /** * Get address. * * \param i index * \return address */ virtual char* getAddress(const size_t i) = 0; /** * Put value at given index. * * \param i index * \param value value */ template void put(const size_t i, const T& value) { * ((T*) getAddress(i)) = value; } }; /** * Interface for parsing data from ROOT data frame to output. */ struct JParser { /** * Virtual destructor. */ virtual ~JParser() {} /** * Parse data. * * \param in input * \param column column name * \param range range * \param out output * \return number of entries parsed */ virtual size_t parse(ROOT::RDataFrame& in, const char* const column, const range_type& range, JOutput& out) const = 0; }; /** * Template implementation for parsing data from ROOT data frame to output. */ template struct JParser_t : public JParser { /** * Parse data. * * \param in input * \param column column name * \param range range * \param out output * \return number of entries parsed */ virtual size_t parse(ROOT::RDataFrame& in, const char* const column, const range_type& range, JOutput& out) const override { size_t i = 0; in.Range(range.getLowerLimit(), range.getUpperLimit()).Foreach([&](T value) { out.put(i++, value); }, { column }); return i; } }; public: /** * Dictionary for parsing data from ROOT data frame to output. */ struct JDictionary : public std::map >, public JSingleton { JDictionary() { add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); add(); } /** * Get typename for given template class. * * This method uses the TDictionary class to get the name of the given class. * * \return type name */ template static const char* getTypename() { const TDictionary* pDictionary = TDictionary::GetDictionary(typeid(T)); if (pDictionary != NULL) return pDictionary->GetName(); else THROW(JException, "Data type not implemented."); } /** * Add parser for given class to dictionary. */ template void add() { (*this)[getTypename()].reset(new JDataFrame::JParser_t()); } }; /** * Auxiliary buffer for parsing data from ROOT data frame. */ template struct JBuffer : public std::vector { /** * Default constructor. */ JBuffer() : cs(TClass::GetClass()) { if (!cs) { THROW(JException, "Data type not defined via ROOT TClass."); } } /** * Parse data. * * \param in input * \param range range * \return number of entries parsed */ size_t operator()(ROOT::RDataFrame& in, const range_type& range) { size_t N = range.getUpperLimit() - range.getLowerLimit(); if (N != 0) { this->resize(N); for (const std::string& column : in.GetColumnNames()) { TDataMember* ps = cs->GetDataMember(column.c_str()); if (ps != NULL && JDictionary::getInstance().count(ps->GetTypeName()) != 0) { JOutput_t out(*this, ps->GetOffset()); N = std::min(N, JDictionary::getInstance()[ps->GetTypeName()]->parse(in, column.c_str(), range, out)); } else { THROW(JException, "Data type not implemented for column " << column); } } } return N; } private: TClass* cs = NULL; /** * Template implementation for output. */ struct JOutput_t : public JDataFrame::JOutput { /** * Constructor * * \param data data * \param offset offset */ JOutput_t(std::vector& data, const int offset) : data(data), offset(offset) {} /** * Get address. * * \param i index * \return address */ virtual char* getAddress(const size_t i) override { return ((char*) &(data[i])) + offset; } private: std::vector& data; const int offset; }; }; }; } #endif