diff --git a/analyzers/dataframe/FCCAnalyses/Defines.h b/analyzers/dataframe/FCCAnalyses/Defines.h index e537dd536e..ffb62d81bd 100644 --- a/analyzers/dataframe/FCCAnalyses/Defines.h +++ b/analyzers/dataframe/FCCAnalyses/Defines.h @@ -1,34 +1,30 @@ #ifndef DEFINES_ANALYZERS_H #define DEFINES_ANALYZERS_H -// std -#include -#include -#include - // ROOT #include "ROOT/RVec.hxx" #include "TLorentzVector.h" // EDM4hep #include "edm4hep/MCParticleData.h" -#include "edm4hep/ParticleIDData.h" #include "edm4hep/ReconstructedParticleData.h" /** * @brief FCC analyzers collection. */ namespace FCCAnalyses { -using Vec_b = ROOT::VecOps::RVec; -using Vec_d = ROOT::VecOps::RVec; -using Vec_f = ROOT::VecOps::RVec; -using Vec_i = ROOT::VecOps::RVec; -using Vec_ui = ROOT::VecOps::RVec; + using Vec_b = ROOT::VecOps::RVec; + using Vec_d = ROOT::VecOps::RVec; + using Vec_f = ROOT::VecOps::RVec; + using Vec_i = ROOT::VecOps::RVec; + using Vec_ui = ROOT::VecOps::RVec; -using rp = edm4hep::ReconstructedParticleData; -using Vec_rp = ROOT::VecOps::RVec; -using Vec_mc = ROOT::VecOps::RVec; -using Vec_tlv = ROOT::VecOps::RVec; + using rp = edm4hep::ReconstructedParticleData; + using Vec_rp = ROOT::VecOps::RVec; + using Vec_mc = ROOT::VecOps::RVec; + using Vec_tlv = ROOT::VecOps::RVec; } // namespace FCCAnalyses +namespace recoParticle = FCCAnalyses::ReconstructedParticle::Source; + #endif diff --git a/analyzers/dataframe/FCCAnalyses/ReconstructedParticleSource.h b/analyzers/dataframe/FCCAnalyses/ReconstructedParticleSource.h index c3b72871cf..d8c9e50ad6 100644 --- a/analyzers/dataframe/FCCAnalyses/ReconstructedParticleSource.h +++ b/analyzers/dataframe/FCCAnalyses/ReconstructedParticleSource.h @@ -8,19 +8,22 @@ #include "edm4hep/ReconstructedParticleCollection.h" #include "edm4hep/MCRecoParticleAssociationCollection.h" -namespace FCCAnalyses :: ReconstructedParticle { +namespace FCCAnalyses :: ReconstructedParticle :: Source { + // -------------------- Selectors ----------------------------------------- + + /** * \brief Analyzer to select reconstructed particles associated with MC * particle of the specified PDG ID. */ struct selPDG { + const int m_pdg; /** * \brief Constructor. * * \param[in] pdgID Desired value of the PDG ID. */ explicit selPDG(const int pdgID); - const int m_pdg; /** * \brief Operator over the input particle collection. * @@ -38,13 +41,13 @@ namespace FCCAnalyses :: ReconstructedParticle { * particle with the specified absolute value of the PDG ID. */ struct selAbsPDG { + const int m_absPdg; /** * \brief Constructor. * * \param[in] pdgID Desired absolute value of the PDG ID. */ explicit selAbsPDG(const int pdgID); - const int m_absPdg; /** * \brief Operator over input particle associations collection. * @@ -58,17 +61,40 @@ namespace FCCAnalyses :: ReconstructedParticle { }; + /** + * \brief Select reconstructed particles with transverse momentum greater + * than a minimum value [GeV]. + */ + struct selPt { + const float m_minPt; + /** + * \brief Constructor. + * + * \param[in] minPt Transverse momentum threshold [GeV]. + */ + explicit selPt(float minPt); + /** + * \brief Operator over input particle associations collection. + * + * \param[in] inColl Input collection of the reconstructed particles. + * \param[out] result Collection of the selected reconstructed particles. + */ + edm4hep::ReconstructedParticleCollection operator() ( + const edm4hep::ReconstructedParticleCollection& inColl); + }; + + /** * \brief Analyzer to select specified number of reconstructed particles. */ struct selUpTo { + const size_t m_size; /** * \brief Constructor. * * \param[in] size Desired number of reconstructed particles. */ explicit selUpTo(const size_t size); - const size_t m_size; /** * \brief Operator over input particle associations collection. * @@ -85,13 +111,13 @@ namespace FCCAnalyses :: ReconstructedParticle { * particle of the desired generator status. */ struct selGenStatus { + const int m_status; /** * \brief Constructor. * * \param[in] status Desired generator status of the MC particle. */ explicit selGenStatus(const int status); - const int m_status; /** * \brief Operator over input particle associations collection. * @@ -103,24 +129,127 @@ namespace FCCAnalyses :: ReconstructedParticle { }; + // -------------------- Getters ------------------------------------------- + + + /** + * \brief Get momenta of the input reconstructed particles. + * + * \param[in] inColl Input particle collection. + * \param[out] result Vector of particle momenta. + */ + ROOT::VecOps::RVec + getP(const edm4hep::ReconstructedParticleCollection& inColl); + + /** * \brief Get transverse momenta (pT) of the input particles. * - * \param[in] inParticles Input particles. + * \param[in] inColl Input particle collection. * \param[out] result Vector of particle pTs. */ - ROOT::VecOps::RVec - getPt(const edm4hep::ReconstructedParticleCollection& inParticles); + ROOT::VecOps::RVec + getPt(const edm4hep::ReconstructedParticleCollection& inColl); + + + /** + * \brief Get rapidity (y) of the input reconstructed particles. + * + * \param[in] inColl Input particle collection. + * \param[out] result Vector of particle rapidities. + */ + ROOT::VecOps::RVec + getY(const edm4hep::ReconstructedParticleCollection& inColl); + + + /** + * \brief Get energy (E) of the input reconstructed particles. + * + * \param[in] inColl Input particle collection. + * \param[out] result Vector of particle energies. + */ + ROOT::VecOps::RVec + getE(const edm4hep::ReconstructedParticleCollection& inColl); + + + /** + * \brief Get mass of the input reconstructed particles. + * + * \param[in] inColl Input particle collection. + * \param[out] result Vector of particle masses. + */ + ROOT::VecOps::RVec + getMass(const edm4hep::ReconstructedParticleCollection& inColl); + + + /** + * \brief Get charge of the input reconstructed particles. + * + * \param[in] inColl Input particle collection. + * \param[out] result Vector of particle charges. + */ + ROOT::VecOps::RVec + getCharge(const edm4hep::ReconstructedParticleCollection& inColl); + + + // -------------------- Transformers -------------------------------------- /** * \brief Sort input particles by pT. * - * \param[in] inParticles Input particles. + * \param[in] inColl Input particles. * \param[out] result Sorted collection of particles. */ edm4hep::ReconstructedParticleCollection - sortByPt(const edm4hep::ReconstructedParticleCollection& inParticles); -} /* FCCAnalyses :: ReconstructedParticle */ + sortByPt(const edm4hep::ReconstructedParticleCollection& inColl); + + + /** + * \brief Build two particle resonances from an arbitrary list of input + * reconstructed particles. + * Select the one closest to the pre-defined mass. + */ + struct resonanceBuilder { + const float m_resonanceMass; + /** + * \brief Constructor. + * + * \param[in] resonanceMass Desired value of the resonance mass. + */ + explicit resonanceBuilder(float resonanceMass); + /** + * \brief Operator over input particle collection. + * + * \param[in] inColl Input collection of the reconstructed particles. + * \param[out] result Selected reconstructed particle resonance. + */ + edm4hep::ReconstructedParticleCollection operator() ( + const edm4hep::ReconstructedParticleCollection& inColl); + }; + + /** + * \brief Build the recoil from an arbitrary list of input resonances at the + * specified center of mass energy. + */ + struct recoilBuilder { + const float m_sqrts; + /** + * \brief Constructor. + * + * \param[in] sqrts Center of mass energy. + */ + explicit recoilBuilder(float sqrts); + /** + * \brief Operator over input collection of resonances. + * + * \param[in] inColl Input collection of resonances. + * \param[out] result Resulting recoil. + */ + edm4hep::ReconstructedParticleCollection operator() ( + const edm4hep::ReconstructedParticleCollection& inColl); + }; + +} /* FCCAnalyses :: ReconstructedParticle :: Source */ #endif /* RECONSTRUCTED_PARTICLE_SOURCE_ANALYZERS_H */ diff --git a/analyzers/dataframe/src/ReconstructedParticleSource.cc b/analyzers/dataframe/src/ReconstructedParticleSource.cc index 75ebaa600a..52b2bd8c13 100644 --- a/analyzers/dataframe/src/ReconstructedParticleSource.cc +++ b/analyzers/dataframe/src/ReconstructedParticleSource.cc @@ -10,6 +10,7 @@ // ROOT #include #include +#include #define rdfFatal R__LOG_FATAL(ROOT::Detail::RDF::RDFLogChannel()) @@ -18,7 +19,7 @@ #define rdfInfo R__LOG_INFO(ROOT::Detail::RDF::RDFLogChannel()) -namespace FCCAnalyses :: ReconstructedParticle { +namespace FCCAnalyses :: ReconstructedParticle :: Source { selPDG::selPDG(const int pdg): m_pdg(pdg) {}; edm4hep::ReconstructedParticleCollection selPDG::operator() ( @@ -26,8 +27,7 @@ namespace FCCAnalyses :: ReconstructedParticle { edm4hep::ReconstructedParticleCollection result; result.setSubsetCollection(); - rdfInfo << "ReconstructedParticle::selPDG: Assoc. coll size: " - << inAssocColl.size(); + rdfInfo << "Assoc. coll size: " << inAssocColl.size(); for (const auto& assoc: inAssocColl) { const auto& particle = assoc.getSim(); @@ -53,9 +53,6 @@ namespace FCCAnalyses :: ReconstructedParticle { edm4hep::ReconstructedParticleCollection result; result.setSubsetCollection(); - rdfInfo << "ReconstructedParticle::selAbsPDG: Assoc. coll size: " - << inAssocColl.size(); - for (const auto& assoc: inAssocColl) { const auto& particle = assoc.getSim(); if (std::abs(particle.getPDG()) == m_absPdg) { @@ -67,6 +64,30 @@ namespace FCCAnalyses :: ReconstructedParticle { } + // -------------------------------------------------------------------------- + selPt::selPt(float minPt): m_minPt(minPt) { + if (m_minPt < 0) { + throw std::invalid_argument("ReconstructedParticle::selPt: Provided " + "pT threshold is negative!"); + } + }; + + edm4hep::ReconstructedParticleCollection selPt::operator() ( + const edm4hep::ReconstructedParticleCollection& inColl) { + edm4hep::ReconstructedParticleCollection result; + result.setSubsetCollection(); + + for (const auto& particle: inColl) { + if (std::sqrt(std::pow(particle.getMomentum().x, 2) + + std::pow(particle.getMomentum().y, 2)) > m_minPt) { + result.push_back(particle); + } + } + + return result; + } + + // -------------------------------------------------------------------------- selUpTo::selUpTo(const size_t size) : m_size(size) {}; @@ -106,18 +127,101 @@ namespace FCCAnalyses :: ReconstructedParticle { return result; } + // -------------------------------------------------------------------------- + ROOT::VecOps::RVec + getP(const edm4hep::ReconstructedParticleCollection& inColl) { + ROOT::VecOps::RVec result; + + for (const auto& particle: inColl) { + TLorentzVector lVec; + lVec.SetXYZM(particle.getMomentum().x, + particle.getMomentum().y, + particle.getMomentum().z, + particle.getMass()); + result.push_back(static_cast(lVec.P())); + } + return result; + } + + + // -------------------------------------------------------------------------- + ROOT::VecOps::RVec + getPt(const edm4hep::ReconstructedParticleCollection& inColl) { + ROOT::VecOps::RVec result; + + std::transform( + inColl.begin(), inColl.end(), + std::back_inserter(result), + [](edm4hep::ReconstructedParticle p){ + return std::sqrt(std::pow(p.getMomentum().x, 2) + + std::pow(p.getMomentum().y, 2)); + } + ); + + return result; + } + + + // -------------------------------------------------------------------------- + ROOT::VecOps::RVec + getY(const edm4hep::ReconstructedParticleCollection& inColl) { + ROOT::VecOps::RVec result; + + for (const auto& particle: inColl) { + TLorentzVector lVec; + lVec.SetXYZM(particle.getMomentum().x, + particle.getMomentum().y, + particle.getMomentum().z, + particle.getMass()); + result.push_back(static_cast(lVec.Rapidity())); + } + + return result; + } + + + // -------------------------------------------------------------------------- + ROOT::VecOps::RVec + getE(const edm4hep::ReconstructedParticleCollection& inColl) { + ROOT::VecOps::RVec result; + + std::transform( + inColl.begin(), inColl.end(), + std::back_inserter(result), + [](edm4hep::ReconstructedParticle p){ return p.getEnergy(); } + ); + + return result; + } + + + // -------------------------------------------------------------------------- + ROOT::VecOps::RVec + getMass(const edm4hep::ReconstructedParticleCollection& inColl) { + ROOT::VecOps::RVec result; + + std::transform( + inColl.begin(), inColl.end(), + std::back_inserter(result), + [](edm4hep::ReconstructedParticle p){ return p.getMass(); } + ); + + return result; + } + // -------------------------------------------------------------------------- - ROOT::VecOps::RVec - getPt(const edm4hep::ReconstructedParticleCollection& inParticles) { - ROOT::VecOps::RVec result; + ROOT::VecOps::RVec + getCharge(const edm4hep::ReconstructedParticleCollection& inColl) { + ROOT::VecOps::RVec result; - for (const auto& particle: inParticles) { - result.push_back(std::sqrt(std::pow(particle.getMomentum().x, 2) + - std::pow(particle.getMomentum().y, 2))); - } + std::transform( + inColl.begin(), inColl.end(), + std::back_inserter(result), + [](edm4hep::ReconstructedParticle p){ return p.getCharge(); } + ); - return result; + return result; } @@ -149,4 +253,100 @@ namespace FCCAnalyses :: ReconstructedParticle { return outColl; } -} /* FCCAnalyses :: ReconstructedParticle */ + + // -------------------------------------------------------------------------- + resonanceBuilder::resonanceBuilder(float resonanceMass): + m_resonanceMass(resonanceMass) { + if (m_resonanceMass < 0) { + throw std::invalid_argument("ReconstructedParticle::resonanceBuilder: " + "Provided resonance mass is negative!"); + } + } + + edm4hep::ReconstructedParticleCollection resonanceBuilder::operator() ( + const edm4hep::ReconstructedParticleCollection& inColl) { + edm4hep::ReconstructedParticleCollection result; + + if (inColl.size() < 2) { + return result; + } + + // Convert collection into std::vector + std::vector rpVec; + for (const auto& particle: inColl) { + rpVec.emplace_back(particle); + } + + // Loop over all possible combinations + std::vector resonanceVec; + for (auto first = rpVec.begin(); first != rpVec.end(); ++first) { + for (auto second = first + 1; second != rpVec.end(); ++second) { + edm4hep::MutableReconstructedParticle resonance; + resonance.setCharge(first->getCharge() + second->getCharge()); + + TLorentzVector lVec1; + lVec1.SetXYZM(first->getMomentum().x, + first->getMomentum().y, + first->getMomentum().z, + first->getMass()); + + TLorentzVector lVec2; + lVec2.SetXYZM(second->getMomentum().x, + second->getMomentum().y, + second->getMomentum().z, + second->getMass()); + + auto lVec = lVec1 + lVec2; + resonance.setMomentum({static_cast(lVec.Px()), + static_cast(lVec.Py()), + static_cast(lVec.Pz())}); + resonance.setMass(static_cast(lVec.M())); + resonanceVec.emplace_back(resonance); + } + } + + // Sort by the distance from desired mass value + auto resonanceSort = [&](edm4hep::ReconstructedParticle i, + edm4hep::ReconstructedParticle j) { + return std::fabs(m_resonanceMass - i.getMass()) < + std::fabs(m_resonanceMass - j.getMass()); + }; + std::sort(resonanceVec.begin(), resonanceVec.end(), resonanceSort); + result.push_back(resonanceVec.front().clone()); + + return result; + } + + + // -------------------------------------------------------------------------- + recoilBuilder::recoilBuilder(float sqrts): m_sqrts(sqrts) { + if (m_sqrts < 0) { + throw std::invalid_argument("ReconstructedParticle::recoilBuilder: " + "Provided center-of-mass is negative!"); + } + } + + edm4hep::ReconstructedParticleCollection recoilBuilder::operator() ( + const edm4hep::ReconstructedParticleCollection& inColl) { + edm4hep::ReconstructedParticleCollection result; + + auto recoilVec = TLorentzVector(0, 0, 0, m_sqrts); + for (const auto& r: inColl) { + auto lVec = TLorentzVector(r.getMomentum().x, + r.getMomentum().y, + r.getMomentum().z, + r.getMass()); + recoilVec -= lVec; + } + + edm4hep::MutableReconstructedParticle recoil; + recoil.setMomentum({static_cast(recoilVec.Px()), + static_cast(recoilVec.Py()), + static_cast(recoilVec.Pz())}); + recoil.setMass(static_cast(recoilVec.M())); + result.push_back(recoil); + + return result; + }; + +} /* FCCAnalyses :: ReconstructedParticle :: Source */ diff --git a/e4hsource/test/analysis_stage1.py b/e4hsource/test/analysis_stage1.py new file mode 100644 index 0000000000..3d740a7666 --- /dev/null +++ b/e4hsource/test/analysis_stage1.py @@ -0,0 +1,136 @@ +''' +First stage +''' + +# Mandatory: +# List of processes used in the analysis +processList = { + # Run over the full statistics and save it to one output file named + # /.root + 'p8_ee_ZZ_ecm240': {'fraction': 0.005}, + # Run over 50% of the statistics and save output into two files named + # /p8_ee_WW_ecm240/chunk.root + 'p8_ee_WW_ecm240': {'fraction': 0.5, 'chunks': 2}, + # Run over 20% of the statistics and save output into one file named + # /p8_ee_ZH_ecm240_out.root + 'p8_ee_ZH_ecm240': {'fraction': 0.2, 'output': 'p8_ee_ZH_ecm240_out'} +} + +# Mandatory: +# Production tag when running over EDM4Hep centrally produced events, this +# points to the yaml files for getting sample statistics +prodTag = "FCCee/spring2021/IDEA/" + +# Optional: +# Output directory, default is local running directory +outputDir = "outputs/source" + +# Optional: +# Name of the analysis, default is "" +# analysisName = "My Analysis" + +# Optional: +# Number of threads to run on, default is 4 +# nCPUS = 4 + +# Optional: +# Optional running on HTCondor, default is False +# runBatch = False + +# Optional: +# Batch queue name when running on HTCondor, default is workday +# batchQueue = "longlunch" + +# Optional: +# Computing account when running on HTCondor, default is group_u_FCC.local_gen +# compGroup = "group_u_FCC.local_gen" + +# Optional: +# How to read the input files +useDataSource = True + +# Optional: +# Test file location +# testFile = 'https://fccsw.web.cern.ch/fccsw/testsamples/' \ +# 'edm4hep1/p8_ee_WW_ecm240_edm4hep.root' +testFile = 'input/30k/p8_ee_ZH_ecm240_edm4hep.root' + + +# Mandatory: +# RDFanalysis class where the user defines the operations on the input +# collections +class RDFanalysis(): + ''' + Analysis class. + ''' + def __init__(self): + self.column_list = [ + "selected_muons_pt", + "selected_muons_y", + "selected_muons_p", + "selected_muons_e", + "zed_leptonic_pt", + "zed_leptonic_m", + "zed_leptonic_charge", + "zed_leptonic_recoil_m" + ] + + # Mandatory: + # Analysers function to define the analysers to process, please make sure + # you return the last dataframe, in this example it is dframe2 + def analysers(dframe): + ''' + Defining operations on the dataframe. + ''' + dframe2 = ( + dframe + # select muons on pT + .Define("selected_muons", "recoParticle::selPt(10.)(Muon)") + # create column with muon transverse momentum + .Define("selected_muons_pt", "recoParticle::getPt(selected_muons)") + # create column with muon rapidity + .Define("selected_muons_y", "recoParticle::getY(selected_muons)") + # create column with muon total momentum + .Define("selected_muons_p", "recoParticle::getP(selected_muons)") + # create column with muon energy + .Define("selected_muons_e", "recoParticle::getE(selected_muons)") + # find zed candidates from di-muon resonances + .Define("zed_leptonic", + "recoParticle::resonanceBuilder(91)(selected_muons)") + # create column with zed transverse momenta + .Define("zed_leptonic_pt", "recoParticle::getPt(zed_leptonic)") + # create column with zed mass + .Define("zed_leptonic_m", "recoParticle::getMass(zed_leptonic)") + # create column with leptonic charge + .Define("zed_leptonic_charge", + "recoParticle::getCharge(zed_leptonic)") + # calculate recoil of zed_leptonic + .Define("zed_leptonic_recoil", + "recoParticle::recoilBuilder(240)(zed_leptonic)") + # create column with recoil mass + .Define("zed_leptonic_recoil_m", + "recoParticle::getMass(zed_leptonic_recoil)") + # Filter on at least one candidate + .Filter("zed_leptonic_recoil_m.size() > 0") + ) + return dframe2 + + # Mandatory: + # Output function, please make sure you return the column list as a python + # list + def output(): + ''' + Which columns to snapshot. + ''' + branchList = [ + "selected_muons_pt", + "selected_muons_y", + "selected_muons_p", + "selected_muons_e", + "zed_leptonic_pt", + "zed_leptonic_m", + "zed_leptonic_charge", + "zed_leptonic_recoil_m" + ] + + return branchList diff --git a/e4hsource/test/histmaker_source.py b/e4hsource/test/histmaker_source.py index a63d36e3ee..c06df30f49 100644 --- a/e4hsource/test/histmaker_source.py +++ b/e4hsource/test/histmaker_source.py @@ -37,11 +37,11 @@ def build_graph(df, dataset): df = df.Define( "electron_truth", - "FCCAnalyses::ReconstructedParticle::selAbsPDG(11)(MCRecoAssociations)") + "recoParticle::selAbsPDG(11)(MCRecoAssociations)") df = df.Define( "electron_truth_pt", - "FCCAnalyses::ReconstructedParticle::getPt(electron_truth)") + "recoParticle::getPt(electron_truth)") results.append(df.Histo1D(("h_electron_truth_pt", "", *bins_pt), "electron_truth_pt")) diff --git a/e4hsource/test/stages_source.py b/e4hsource/test/stages_source.py index a2c5b94082..ad42225fd1 100644 --- a/e4hsource/test/stages_source.py +++ b/e4hsource/test/stages_source.py @@ -31,18 +31,18 @@ def analysers(df): df .Define( "electron_truth", - "FCCAnalyses::ReconstructedParticle::selPDG(11)(MCRecoAssociations)") + "recoParticle::selPDG(11)(MCRecoAssociations)") .Define( "electron_truth_pt", - "FCCAnalyses::ReconstructedParticle::getPt(electron_truth)") + "recoParticle::getPt(electron_truth)") ) return df2 def output(): branchList = [ - "electron_truth", + # "electron_truth", "electron_truth_pt" ] diff --git a/e4hsource/test/standalone.py b/e4hsource/test/standalone.py index eb617e4f83..c18927bd76 100644 --- a/e4hsource/test/standalone.py +++ b/e4hsource/test/standalone.py @@ -25,11 +25,11 @@ def main(): dframe2 = dframe.Define( "electron_truth", - "FCCAnalyses::ReconstructedParticle::selPDG(11)(MCRecoAssociations)") + "recoParticle::selPDG(11)(MCRecoAssociations)") dframe3 = dframe2.Define( "electron_truth_pt", - "FCCAnalyses::ReconstructedParticle::getPt(electron_truth)") + "recoParticle::getPt(electron_truth)") dframe4 = dframe3.Filter("electron_truth_pt.size() < 3") diff --git a/examples/FCCee/higgs/mH-recoil/mumu/analysis_stage1.py b/examples/FCCee/higgs/mH-recoil/mumu/analysis_stage1.py index 7d8f325111..98f6f1214a 100644 --- a/examples/FCCee/higgs/mH-recoil/mumu/analysis_stage1.py +++ b/examples/FCCee/higgs/mH-recoil/mumu/analysis_stage1.py @@ -27,7 +27,8 @@ #compGroup = "group_u_FCC.local_gen" #Optional test file -testFile ="/eos/experiment/fcc/ee/generation/DelphesEvents/spring2021/IDEA/p8_ee_ZH_ecm240/events_101027117.root" +# testFile ="/eos/experiment/fcc/ee/generation/DelphesEvents/spring2021/IDEA/p8_ee_ZH_ecm240/events_101027117.root" +testFile = 'input/30k/p8_ee_ZH_ecm240_edm4hep.root' #Mandatory: RDFanalysis class where the use defines the operations on the TTree class RDFanalysis(): @@ -38,7 +39,7 @@ def analysers(df): df2 = ( df # define an alias for muon index collection - .Alias("Muon0", "Muon#0.index") + .Alias("Muon0", "Muon_objIdx.index") # define the muon collection .Define("muons", "ReconstructedParticle::get(Muon0, ReconstructedParticles)") #select muons on pT diff --git a/python/anascript.py b/python/anascript.py index f06ed07b9d..ad90f708af 100644 --- a/python/anascript.py +++ b/python/anascript.py @@ -26,7 +26,7 @@ def get_element(rdf_module, element: str, is_final: bool = False): elif element == 'analysers': LOGGER.error('The function <%s> is mandatory in your analysis ' - 'script!.\nAborting...', element) + 'script!\nAborting...', element) if is_final: LOGGER.error('The function <%s> is not part of the final ' 'stage of the analysis!', element) diff --git a/python/run_analysis.py b/python/run_analysis.py index 0f71ca9b46..024f70de36 100644 --- a/python/run_analysis.py +++ b/python/run_analysis.py @@ -355,9 +355,9 @@ def run_rdf(rdf_module, generate_graph(dframe, args) dframe3.Snapshot("events", out_file, branch_list) - except cppyy.gbl.std.runtime_error: - LOGGER.error('During the execution of the analysis script an ' - 'exception occurred!\nAborting...') + except cppyy.gbl.std.runtime_error as err: + LOGGER.error('%s\nDuring the execution of the analysis script an ' + 'exception occurred!\nAborting...', err) sys.exit(3) return evtcount.GetValue() diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c5e280131d..3bb8b1b524 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -10,6 +10,7 @@ add_integration_test("examples/FCCee/vertex_lcfiplus/analysis_V0.py") if(WITH_SOURCE) add_integration_test("e4hsource/test/histmaker_source.py") add_integration_test("e4hsource/test/stages_source.py") + add_integration_test("e4hsource/test/analysis_stage1.py") add_standalone_test("e4hsource/test/standalone.py") endif()