Support for command line arguments

Hi,

I have an analysis that studies a number of decays, e.g Bd2KstNuNu, Kst->K pi and Bs2PhiNuNu, phi->KK, and uses a BDT at each analysis stage to reduce bkgs. Previously I ran this via snakemake but I’m now updating it to be more like the higgs/mH-recoil/mumu/ analysis example and using the built in input/output management, but this doesn’t seem to support command line arguments. I could handle this by writing a separate stage1 script for each decay, and load in the MVA cut value from a JSON or something that gets written by the BDT training but this seems like a lot of duplication and prone to bugs. But ideally I’d like to tell it via the command line what decay it is, what the relevant PDGIDs for that is etc… Is there a way to have fccanalysis run <script> support passing arguments to my script? Looking at this it seems like the answer is no. Would there be interest in having this added? Not that I know how that would be done :wink:

Thanks for any help,

Aidan

Hi @aiwieder,

at the moment passing of the arguments to the analysis script is not possible, but it should be possible to pass them to the RDFanalysis class if we adjust a little its signature. I will try to investigate all the consequencies…

Can you share a mockup script how you would imagine the arguments will be used in the script?

Best,
Juraj

Hi @jsmiesko,

Here is a version of our stage1 where I’ve hard coded what I’d like the arguments to be and added a little bit of info about what the other possible values could be. Then in the rest you can see how I use these arguments.

Thanks,

Aidan

#import argparse
#parser = argparse.ArgumentParser(description="Applies preselection cuts", formatter_class=argparse.ArgumentDefaultsHelpFormatter)
#parser.add_argument('--input',nargs="+", required=True, help='Select the input file(s).')
#parser.add_argument('--output', type=str, required=True, help='Select the output file.')
#parser.add_argument('--MVA_cut', default = -1., type=float, help='Choose the MVA cut.')
#parser.add_argument('--n_events', default = 0, type=int, help='Choose the number of events to process.')
#parser.add_argument('--n_cpus', default = 8, type=int, help='Choose the number of cpus to use.')
#parser.add_argument('--decay', required=True, type=str, help='Choose the decay to reconstruct.')
#parser.add_argument('--mva', default="", type=str, help='Path to the trained MVA ROOT file.')
#parser.add_argument("--training", default=False, action="store_const", const=True, help="prepare tuples for BDT training.")
#args = parser.parse_args()

# this could also use a cmd argument 
#nCPUS       = 8

processList = {
    "p8_ee_Zbb_ecm91_EvtGen_Bd2KstNuNu": {"fraction": 0.1, "chunks": 20},
    "p8_ee_Zbb_ecm91":  {"fraction": 0.1, "chunks": 20},
    "p8_ee_Zcc_ecm91":  {"fraction": 0.1, "chunks": 20},
    "p8_ee_Zuds_ecm91": {"fraction": 0.1, "chunks": 20},
}

prodTag = "FCCee/spring2021/IDEA"

outputDir = "outputs/FCCee/flavour/b2snunu/stage1"

testFile = "root://eospublic.cern.ch//eos/experiment/fcc/ee/generation/DelphesEvents/spring2021/IDEA/p8_ee_Zuds_ecm91/events_171273643.root"

class RDFanalysis():

    def analysers(df):
        print("Running...")

        # hard coding what could be command line arguments
        candidates = "KPi" # or "PiPi" "KK" "pPi"
        decay = "Bd2KstNuNu" # or "Bs2PhiNuNu" "Bd2KsNuNu" "Lb2LNuNu"
        parent_pdgid = 511 # or 531 511 5122
        child_pdgid = 313 # or 333 310 3122
        training = True # or False
        mva = "path/to/MVA.root" # path can depend on the decay
        MVA_cut = 0.6 # or another float

        if not args.training:
            assert(args.mva!="")
            ROOT.gInterpreter.ProcessLine(f'''
            TMVA::Experimental::RBDT<> bdt("{args.decay}_BDT", "{args.mva}");
            computeModel = TMVA::Experimental::Compute<18, float>(bdt);
            ''')
            MVAFilter=f"EVT_MVA1>{MVA_cut}"
        
        df3 = (df
               #############################################
               ##          Aliases for # in python        ##
               #############################################
               .Alias("MCRecoAssociations0", "MCRecoAssociations#0.index")
               .Alias("MCRecoAssociations1", "MCRecoAssociations#1.index")
               .Alias("Particle0", "Particle#0.index")
               .Alias("Particle1", "Particle#1.index")


               #############################################
               ##MC record to study the Z->bb events types##
               #############################################               
               .Define("MC_PDG", "FCCAnalyses::MCParticle::get_pdg(Particle)")
               .Define("MC_n",   "int(MC_PDG.size())")
               .Define("MC_M1",  "FCCAnalyses::myUtils::get_MCMother1(Particle,Particle0)")
               .Define("MC_M2",  "FCCAnalyses::myUtils::get_MCMother2(Particle,Particle0)")
               .Define("MC_D1",  "FCCAnalyses::myUtils::get_MCDaughter1(Particle,Particle1)")
               .Define("MC_D2",  "FCCAnalyses::myUtils::get_MCDaughter2(Particle,Particle1)")
               .Define("MC_M1",  "FCCAnalyses::myUtils::getMC_parent(0,Particle,Particle0)")
               .Define("MC_M2",  "FCCAnalyses::myUtils::getMC_parent(1,Particle,Particle0)")
               .Define("MC_D1",  "FCCAnalyses::myUtils::getMC_daughter(0,Particle,Particle1)")
               .Define("MC_D2",  "FCCAnalyses::myUtils::getMC_daughter(1,Particle,Particle1)")
               .Define("MC_D3",  "FCCAnalyses::myUtils::getMC_daughter(2,Particle,Particle1)")
               .Define("MC_D4",  "FCCAnalyses::myUtils::getMC_daughter(3,Particle,Particle1)")
               .Define("MC_orivtx_x",   "FCCAnalyses::MCParticle::get_vertex_x(Particle)")
               .Define("MC_orivtx_y",   "FCCAnalyses::MCParticle::get_vertex_y(Particle)")
               .Define("MC_orivtx_z",   "FCCAnalyses::MCParticle::get_vertex_z(Particle)")
               .Define("MC_endvtx_x",   "FCCAnalyses::MCParticle::get_endPoint_x(Particle)")
               .Define("MC_endvtx_y",   "FCCAnalyses::MCParticle::get_endPoint_y(Particle)")
               .Define("MC_endvtx_z",   "FCCAnalyses::MCParticle::get_endPoint_z(Particle)")
               .Define("MC_p",   "FCCAnalyses::MCParticle::get_p(Particle)")
               .Define("MC_pt",  "FCCAnalyses::MCParticle::get_pt(Particle)")
               .Define("MC_px",  "FCCAnalyses::MCParticle::get_px(Particle)")
               .Define("MC_py",  "FCCAnalyses::MCParticle::get_py(Particle)")
               .Define("MC_pz",  "FCCAnalyses::MCParticle::get_pz(Particle)")
               .Define("MC_e",   "FCCAnalyses::MCParticle::get_e(Particle)")
               .Define("MC_m",   "FCCAnalyses::MCParticle::get_mass(Particle)")
               .Define("MC_q",   "FCCAnalyses::MCParticle::get_charge(Particle)")
               .Define("MC_eta", "FCCAnalyses::MCParticle::get_eta(Particle)")
               .Define("MC_phi", "FCCAnalyses::MCParticle::get_phi(Particle)")
               

               #############################################
               ##               Build MC Vertex           ##
               #############################################
               .Define("MCVertexObject", "FCCAnalyses::myUtils::get_MCVertexObject(Particle, Particle0)")
               .Define("MC_Vertex_x",    "FCCAnalyses::myUtils::get_MCVertex_x(MCVertexObject)")
               .Define("MC_Vertex_y",    "FCCAnalyses::myUtils::get_MCVertex_y(MCVertexObject)")
               .Define("MC_Vertex_z",    "FCCAnalyses::myUtils::get_MCVertex_z(MCVertexObject)")
               .Define("MC_Vertex_ind",  "FCCAnalyses::myUtils::get_MCindMCVertex(MCVertexObject)")
               .Define("MC_Vertex_ntrk", "FCCAnalyses::myUtils::get_NTracksMCVertex(MCVertexObject)")
               .Define("MC_Vertex_n",    "int(MC_Vertex_x.size())")
               .Define("MC_Vertex_PDG",  "FCCAnalyses::myUtils::get_MCpdgMCVertex(MCVertexObject, Particle)")
               .Define("MC_Vertex_PDGmother",  "FCCAnalyses::myUtils::get_MCpdgMotherMCVertex(MCVertexObject, Particle)")
               .Define("MC_Vertex_PDGgmother", "FCCAnalyses::myUtils::get_MCpdgGMotherMCVertex(MCVertexObject, Particle)")
        )
        if decay[:2] in ["Lb", "KS"]:
            df4 = (df3
                #############################################
                ##               Build V0s                 ##
                #############################################
                    .Define("SecondaryTracks",   "VertexFitterSimple::get_NonPrimaryTracks( EFlowTrack_1,  RecoedPrimaryTracks )")

                    .Define("V0_evt", "VertexFinderLCFIPlus::get_V0s(SecondaryTracks, PrimaryVertexObject, true)")
            )
        else:
            df4 = df3

        df5 = (df4

               #############################################
               ##              Build Reco Vertex          ##
               #############################################
               .Define("VertexObject", "FCCAnalyses::myUtils::get_VertexObject(MCVertexObject,ReconstructedParticles,EFlowTrack_1,MCRecoAssociations0,MCRecoAssociations1)")
               .Define("VertexObject",  "VertexFitterSimple::VertexFitter_Tk ( 1, EFlowTrack_1, true, 4.5, 20e-3, 300)")


               #############################################
               ##          Build PV var and filter        ##
               #############################################
               .Define("EVT_hasPV",    "FCCAnalyses::myUtils::hasPV(VertexObject)")
               .Define("EVT_NtracksPV", "float(FCCAnalyses::myUtils::get_PV_ntracks(VertexObject))")
               .Define("EVT_NVertex",   "float(VertexObject.size())")
               #.Filter("EVT_hasPV==1")


               #############################################
               ##          Build RECO P with PID          ##
               #############################################
               .Define("RecoPartPID" ,f"FCCAnalyses::myUtils::PID(ReconstructedParticles, MCRecoAssociations0,MCRecoAssociations1,Particle)")
               

               #############################################
               ##    Build RECO P with PID at vertex      ##
               #############################################
               .Define("RecoPartPIDAtVertex" ,"FCCAnalyses::myUtils::get_RP_atVertex(RecoPartPID, VertexObject)")


               #############################################
               ##         Build vertex variables          ##
               #############################################
               .Define("Vertex_x",        "FCCAnalyses::myUtils::get_Vertex_x(VertexObject)")
               .Define("Vertex_y",        "FCCAnalyses::myUtils::get_Vertex_y(VertexObject)")
               .Define("Vertex_z",        "FCCAnalyses::myUtils::get_Vertex_z(VertexObject)")
               .Define("Vertex_xErr",     "FCCAnalyses::myUtils::get_Vertex_xErr(VertexObject)")
               .Define("Vertex_yErr",     "FCCAnalyses::myUtils::get_Vertex_yErr(VertexObject)")
               .Define("Vertex_zErr",     "FCCAnalyses::myUtils::get_Vertex_zErr(VertexObject)")

               .Define("Vertex_chi2",     "FCCAnalyses::myUtils::get_Vertex_chi2(VertexObject)")
               .Define("Vertex_mcind",    "FCCAnalyses::myUtils::get_Vertex_indMC(VertexObject)")
               .Define("Vertex_ind",      "FCCAnalyses::myUtils::get_Vertex_ind(VertexObject)")
               .Define("Vertex_isPV",     "FCCAnalyses::myUtils::get_Vertex_isPV(VertexObject)")
               .Define("Vertex_ntrk",     "FCCAnalyses::myUtils::get_Vertex_ntracks(VertexObject)")
               .Define("Vertex_n",        "int(Vertex_x.size())")
               .Define("Vertex_mass",     "FCCAnalyses::myUtils::get_Vertex_mass(VertexObject,RecoPartPIDAtVertex)")

               .Define("Vertex_d2PV",     "FCCAnalyses::myUtils::get_Vertex_d2PV(VertexObject,-1)")
               .Define("Vertex_d2PVx",    "FCCAnalyses::myUtils::get_Vertex_d2PV(VertexObject,0)")
               .Define("Vertex_d2PVy",    "FCCAnalyses::myUtils::get_Vertex_d2PV(VertexObject,1)")
               .Define("Vertex_d2PVz",    "FCCAnalyses::myUtils::get_Vertex_d2PV(VertexObject,2)")
               
               .Define("Vertex_d2PVErr",  "FCCAnalyses::myUtils::get_Vertex_d2PVError(VertexObject,-1)")
               .Define("Vertex_d2PVxErr", "FCCAnalyses::myUtils::get_Vertex_d2PVError(VertexObject,0)")
               .Define("Vertex_d2PVyErr", "FCCAnalyses::myUtils::get_Vertex_d2PVError(VertexObject,1)")
               .Define("Vertex_d2PVzErr", "FCCAnalyses::myUtils::get_Vertex_d2PVError(VertexObject,2)")
               
               .Define("Vertex_d2PVSig",  "Vertex_d2PV/Vertex_d2PVErr")
               .Define("Vertex_d2PVxSig", "Vertex_d2PVx/Vertex_d2PVxErr")
               .Define("Vertex_d2PVySig", "Vertex_d2PVy/Vertex_d2PVyErr")
               .Define("Vertex_d2PVzSig", "Vertex_d2PVz/Vertex_d2PVzErr")

               .Define("Vertex_d2MC",     "FCCAnalyses::myUtils::get_Vertex_d2MC(VertexObject,MCVertexObject,Vertex_mcind,-1)")
               .Define("Vertex_d2MCx",    "FCCAnalyses::myUtils::get_Vertex_d2MC(VertexObject,MCVertexObject,Vertex_mcind,0)")
               .Define("Vertex_d2MCy",    "FCCAnalyses::myUtils::get_Vertex_d2MC(VertexObject,MCVertexObject,Vertex_mcind,1)")
               .Define("Vertex_d2MCz",    "FCCAnalyses::myUtils::get_Vertex_d2MC(VertexObject,MCVertexObject,Vertex_mcind,2)")

               .Define("EVT_dPV2DVmin",   "FCCAnalyses::myUtils::get_dPV2DV_min(Vertex_d2PV)")
               .Define("EVT_dPV2DVmax",   "FCCAnalyses::myUtils::get_dPV2DV_max(Vertex_d2PV)")
               .Define("EVT_dPV2DVave",   "FCCAnalyses::myUtils::get_dPV2DV_ave(Vertex_d2PV)")
               

               #############################################
               ##        Build Kstz -> KPi  candidates      ##
               #############################################
               .Define(f"{candidates}Candidates",         f"FCCAnalyses::myUtils::build_{decay}(VertexObject,RecoPartPIDAtVertex)")


               #############################################
               ##       Filter Kstz -> KPi candidates      ##
               ############################################# 
               .Define(f"EVT_N{candidates}",              f"float(FCCAnalyses::myUtils::getFCCAnalysesComposite_N({candidates}Candidates))")
               .Filter(f"EVT_N{candidates}>0")


               #############################################
               ##    Attempt to add a truth match         ##
               #############################################
               #.Define("TruthMatching" ,f"FCCAnalyses::myUtils::add_truthmatched2({candidates}Candidates, MCParticles, MCRecoAssociations0, ReconstructedParticles, MCRecoAssociations1)")
               .Define("TruthMatching" ,f"FCCAnalyses::myUtils::add_truthmatched2({candidates}Candidates, Particle, VertexObject, MCRecoAssociations1, ReconstructedParticles, Particle0)")


               #############################################
               ##              Build the thrust           ##
               ############################################# 
               .Define("RP_e",          "FCCAnalyses::ReconstructedParticle::get_e(RecoPartPIDAtVertex)")
               .Define("RP_px",         "FCCAnalyses::ReconstructedParticle::get_px(RecoPartPIDAtVertex)")
               .Define("RP_py",         "FCCAnalyses::ReconstructedParticle::get_py(RecoPartPIDAtVertex)")
               .Define("RP_pz",         "FCCAnalyses::ReconstructedParticle::get_pz(RecoPartPIDAtVertex)")
               .Define("RP_charge",     "FCCAnalyses::ReconstructedParticle::get_charge(RecoPartPIDAtVertex)")
              
               .Define("EVT_thrustNP",      'FCCAnalyses::Algorithms::minimize_thrust("Minuit2","Migrad")(RP_px, RP_py, RP_pz)')
               .Define("RP_thrustangleNP",  'FCCAnalyses::Algorithms::getAxisCosTheta(EVT_thrustNP, RP_px, RP_py, RP_pz)')
               .Define("EVT_thrust",        'FCCAnalyses::Algorithms::getThrustPointing(1.)(RP_thrustangleNP, RP_e, EVT_thrustNP)') # changed from 'Algorithms::getThrustPointing(RP_thrustangleNP, RP_e, EVT_thrustNP, 1.)' because of https://github.com/HEP-FCC/FCCAnalyses/commit/e9c4787f82505115be0c084da4453031c3cf8fdf
               .Define("RP_thrustangle",    'FCCAnalyses::Algorithms::getAxisCosTheta(EVT_thrust, RP_px, RP_py, RP_pz)')

               
               #############################################
               ##        Get thrust related values        ##
               ############################################# 
               ##hemis0 == negative angle == max energy hemisphere if pointing
               ##hemis1 == positive angle == min energy hemisphere if pointing
               .Define("EVT_thrusthemis0_n",    "FCCAnalyses::Algorithms::getAxisN(0)(RP_thrustangle, RP_charge)")
               .Define("EVT_thrusthemis1_n",    "FCCAnalyses::Algorithms::getAxisN(1)(RP_thrustangle, RP_charge)")
               .Define("EVT_thrusthemis0_e",    "FCCAnalyses::Algorithms::getAxisEnergy(0)(RP_thrustangle, RP_charge, RP_e)")
               .Define("EVT_thrusthemis1_e",    "FCCAnalyses::Algorithms::getAxisEnergy(1)(RP_thrustangle, RP_charge, RP_e)")

               .Define("EVT_ThrustEmax_E",         "EVT_thrusthemis0_e.at(0)")
               .Define("EVT_ThrustEmax_Echarged",  "EVT_thrusthemis0_e.at(1)")
               .Define("EVT_ThrustEmax_Eneutral",  "EVT_thrusthemis0_e.at(2)")
               .Define("EVT_ThrustEmax_N",         "float(EVT_thrusthemis0_n.at(0))")
               .Define("EVT_ThrustEmax_Ncharged",  "float(EVT_thrusthemis0_n.at(1))")
               .Define("EVT_ThrustEmax_Nneutral",  "float(EVT_thrusthemis0_n.at(2))")

               .Define("EVT_ThrustEmin_E",         "EVT_thrusthemis1_e.at(0)")
               .Define("EVT_ThrustEmin_Echarged",  "EVT_thrusthemis1_e.at(1)")
               .Define("EVT_ThrustEmin_Eneutral",  "EVT_thrusthemis1_e.at(2)")
               .Define("EVT_ThrustEmin_N",         "float(EVT_thrusthemis1_n.at(0))")
               .Define("EVT_ThrustEmin_Ncharged",  "float(EVT_thrusthemis1_n.at(1))")
               .Define("EVT_ThrustEmin_Nneutral",  "float(EVT_thrusthemis1_n.at(2))")


               .Define("Vertex_thrust_angle",   "FCCAnalyses::myUtils::get_Vertex_thrusthemis_angle(VertexObject, RecoPartPIDAtVertex, EVT_thrust)")
               .Define("DVertex_thrust_angle",  "FCCAnalyses::myUtils::get_DVertex_thrusthemis_angle(VertexObject, RecoPartPIDAtVertex, EVT_thrust)")
               ###0 == negative angle==max energy , 1 == positive angle == min energy
               .Define("Vertex_thrusthemis_emin",    "FCCAnalyses::myUtils::get_Vertex_thrusthemis(Vertex_thrust_angle, 1)")
               .Define("Vertex_thrusthemis_emax",    "FCCAnalyses::myUtils::get_Vertex_thrusthemis(Vertex_thrust_angle, 0)")

               .Define("EVT_ThrustEmin_NDV", "float(FCCAnalyses::myUtils::get_Npos(DVertex_thrust_angle))")
               .Define("EVT_ThrustEmax_NDV", "float(FCCAnalyses::myUtils::get_Nneg(DVertex_thrust_angle))")

               .Define("EVT_Thrust_Mag",  "EVT_thrust.at(0)")
               .Define("EVT_Thrust_X",    "EVT_thrust.at(1)")
               .Define("EVT_Thrust_XErr", "EVT_thrust.at(2)")
               .Define("EVT_Thrust_Y",    "EVT_thrust.at(3)")
               .Define("EVT_Thrust_YErr", "EVT_thrust.at(4)")
               .Define("EVT_Thrust_Z",    "EVT_thrust.at(5)")
               .Define("EVT_Thrust_ZErr", "EVT_thrust.at(6)")


               .Define("DV_tracks", "FCCAnalyses::myUtils::get_pseudotrack(VertexObject,RecoPartPIDAtVertex)")

               .Define("DV_d0",            "FCCAnalyses::myUtils::get_trackd0(DV_tracks)")
               .Define("DV_z0",            "FCCAnalyses::myUtils::get_trackz0(DV_tracks)")

               .Define(f"{candidates}Candidates_mass",    f"FCCAnalyses::myUtils::getFCCAnalysesComposite_mass({candidates}Candidates)")
               .Define(f"{candidates}Candidates_q",       f"FCCAnalyses::myUtils::getFCCAnalysesComposite_charge({candidates}Candidates)")
               .Define(f"{candidates}Candidates_vertex",  f"FCCAnalyses::myUtils::getFCCAnalysesComposite_vertex({candidates}Candidates)")
               .Define(f"{candidates}Candidates_mcvertex",f"FCCAnalyses::myUtils::getFCCAnalysesComposite_mcvertex({candidates}Candidates,VertexObject)")
               .Define(f"{candidates}Candidates_truth",   f"FCCAnalyses::myUtils::getFCCAnalysesComposite_truthMatch(TruthMatching)") # KPiCandidates -> TruthMatching
               .Define(f"{candidates}Candidates_px",      f"FCCAnalyses::myUtils::getFCCAnalysesComposite_p({candidates}Candidates,0)")
               .Define(f"{candidates}Candidates_py",      f"FCCAnalyses::myUtils::getFCCAnalysesComposite_p({candidates}Candidates,1)")
               .Define(f"{candidates}Candidates_pz",      f"FCCAnalyses::myUtils::getFCCAnalysesComposite_p({candidates}Candidates,2)")
               .Define(f"{candidates}Candidates_p",       f"FCCAnalyses::myUtils::getFCCAnalysesComposite_p({candidates}Candidates,-1)")
               .Define(f"{candidates}Candidates_B",       f"FCCAnalyses::myUtils::getFCCAnalysesComposite_B({candidates}Candidates, VertexObject, RecoPartPIDAtVertex)")
               
               .Define(f"{candidates}Candidates_track",   f"FCCAnalyses::myUtils::getFCCAnalysesComposite_track({candidates}Candidates, VertexObject)")
               .Define(f"{candidates}Candidates_d0",      f"FCCAnalyses::myUtils::get_trackd0({candidates}Candidates_track)")
               .Define(f"{candidates}Candidates_z0",      f"FCCAnalyses::myUtils::get_trackz0({candidates}Candidates_track)")

               .Define(f"{candidates}Candidates_anglethrust", f"FCCAnalyses::myUtils::getFCCAnalysesComposite_anglethrust({candidates}Candidates, EVT_thrust)")
               .Define("CUT_hasCandEmin",           f"FCCAnalyses::myUtils::has_anglethrust_emin({candidates}Candidates_anglethrust)")
               #.Filter("CUT_hasCandEmin>0")
               
               .Define(f"{candidates}Candidates_h1px",   f"FCCAnalyses::myUtils::getFCCAnalysesComposite_p({candidates}Candidates, VertexObject, RecoPartPIDAtVertex, 0, 0)")
               .Define(f"{candidates}Candidates_h1py",   f"FCCAnalyses::myUtils::getFCCAnalysesComposite_p({candidates}Candidates, VertexObject, RecoPartPIDAtVertex, 0, 1)")
               .Define(f"{candidates}Candidates_h1pz",   f"FCCAnalyses::myUtils::getFCCAnalysesComposite_p({candidates}Candidates, VertexObject, RecoPartPIDAtVertex, 0, 2)")
               .Define(f"{candidates}Candidates_h1p",    f"FCCAnalyses::myUtils::getFCCAnalysesComposite_p({candidates}Candidates, VertexObject, RecoPartPIDAtVertex, 0, -1)")
               .Define(f"{candidates}Candidates_h1q",    f"FCCAnalyses::myUtils::getFCCAnalysesComposite_q({candidates}Candidates, VertexObject, RecoPartPIDAtVertex, 0)")
               .Define(f"{candidates}Candidates_h1m",    f"FCCAnalyses::myUtils::getFCCAnalysesComposite_mass({candidates}Candidates, VertexObject, RecoPartPIDAtVertex, 0)")
               .Define(f"{candidates}Candidates_h1type", f"FCCAnalyses::myUtils::getFCCAnalysesComposite_type({candidates}Candidates, VertexObject, RecoPartPIDAtVertex, 0)")
               .Define(f"{candidates}Candidates_h1d0",   f"FCCAnalyses::myUtils::getFCCAnalysesComposite_d0({candidates}Candidates, VertexObject, 0)")
               .Define(f"{candidates}Candidates_h1z0",   f"FCCAnalyses::myUtils::getFCCAnalysesComposite_z0({candidates}Candidates, VertexObject, 0)")
               
               .Define(f"{candidates}Candidates_h2px",   f"FCCAnalyses::myUtils::getFCCAnalysesComposite_p({candidates}Candidates, VertexObject, RecoPartPIDAtVertex, 1, 0)")
               .Define(f"{candidates}Candidates_h2py",   f"FCCAnalyses::myUtils::getFCCAnalysesComposite_p({candidates}Candidates, VertexObject, RecoPartPIDAtVertex, 1, 1)")
               .Define(f"{candidates}Candidates_h2pz",   f"FCCAnalyses::myUtils::getFCCAnalysesComposite_p({candidates}Candidates, VertexObject, RecoPartPIDAtVertex, 1, 2)")
               .Define(f"{candidates}Candidates_h2p",    f"FCCAnalyses::myUtils::getFCCAnalysesComposite_p({candidates}Candidates, VertexObject, RecoPartPIDAtVertex, 1, -1)")
               .Define(f"{candidates}Candidates_h2q",    f"FCCAnalyses::myUtils::getFCCAnalysesComposite_q({candidates}Candidates, VertexObject, RecoPartPIDAtVertex, 1)")
               .Define(f"{candidates}Candidates_h2m",    f"FCCAnalyses::myUtils::getFCCAnalysesComposite_mass({candidates}Candidates, VertexObject, RecoPartPIDAtVertex, 1)")
               .Define(f"{candidates}Candidates_h2type", f"FCCAnalyses::myUtils::getFCCAnalysesComposite_type({candidates}Candidates, VertexObject, RecoPartPIDAtVertex, 1)")
               .Define(f"{candidates}Candidates_h2d0",   f"FCCAnalyses::myUtils::getFCCAnalysesComposite_d0({candidates}Candidates, VertexObject, 1)")
               .Define(f"{candidates}Candidates_h2z0",   f"FCCAnalyses::myUtils::getFCCAnalysesComposite_z0({candidates}Candidates, VertexObject, 1)")
               
               .Define(f"True{candidates}_vertex",        f"FCCAnalyses::myUtils::get_trueVertex(MCVertexObject,Particle,Particle0, {child_pdgid}, {parent_pdgid})")
               .Define(f"True{candidates}_track",         f"FCCAnalyses::myUtils::get_truetrack(True{candidates}_vertex, MCVertexObject, Particle)")
               .Define(f"True{candidates}_d0",            f"FCCAnalyses::myUtils::get_trackd0(True{candidates}_track)")
               .Define(f"True{candidates}_z0",            f"FCCAnalyses::myUtils::get_trackz0(True{candidates}_track)")
           )
        
        if not training:
            df6 = (df5
               # Build MVA 
               .Define("MVAVec", ROOT.computeModel, ("EVT_ThrustEmin_E",        "EVT_ThrustEmax_E",
                                                     "EVT_ThrustEmin_Echarged", "EVT_ThrustEmax_Echarged",
                                                     "EVT_ThrustEmin_Eneutral", "EVT_ThrustEmax_Eneutral",
                                                     "EVT_ThrustEmin_Ncharged", "EVT_ThrustEmax_Ncharged",
                                                     "EVT_ThrustEmin_Nneutral", "EVT_ThrustEmax_Nneutral",
                                                     "EVT_NtracksPV",           "EVT_NVertex",
                                                     f"EVT_N{candidates}",                "EVT_ThrustEmin_NDV",
                                                     "EVT_ThrustEmax_NDV",      "EVT_dPV2DVmin",
                                                     "EVT_dPV2DVmax",           "EVT_dPV2DVave"))
               .Define("EVT_MVA1", "MVAVec.at(0)")
               .Filter(MVAFilter)
            )
        else:
            df6 = df5

        return df6

    def output():
        candidates = "KPi"
        decay = "Bd2KstNuNu"
        parent_pdgid = 511
        child_pdgid = 313
        training = True
        desired_branches = [
                "MC_PDG","MC_M1","MC_M2","MC_n","MC_D1","MC_D2","MC_D3","MC_D4",
                "MC_p","MC_pt","MC_px","MC_py","MC_pz","MC_eta","MC_phi",
                "MC_orivtx_x","MC_orivtx_y","MC_orivtx_z", 
                "MC_endvtx_x", "MC_endvtx_y", "MC_endvtx_z", "MC_e","MC_m",
                "EVT_ThrustEmin_E",          "EVT_ThrustEmax_E",
                "EVT_ThrustEmin_Echarged",   "EVT_ThrustEmax_Echarged",
                "EVT_ThrustEmin_Eneutral",   "EVT_ThrustEmax_Eneutral",
                "EVT_ThrustEmin_N",          "EVT_ThrustEmax_N",                
                "EVT_ThrustEmin_Ncharged",   "EVT_ThrustEmax_Ncharged",
                "EVT_ThrustEmin_Nneutral",   "EVT_ThrustEmax_Nneutral",
                "EVT_ThrustEmin_NDV",        "EVT_ThrustEmax_NDV",
                "EVT_Thrust_Mag",
                "EVT_Thrust_X",  "EVT_Thrust_XErr",
                "EVT_Thrust_Y",  "EVT_Thrust_YErr",
                "EVT_Thrust_Z",  "EVT_Thrust_ZErr",

                 "EVT_NtracksPV", 
                 "EVT_NVertex",
                 f"EVT_N{candidates}",
                
                "EVT_dPV2DVmin","EVT_dPV2DVmax","EVT_dPV2DVave",

                "MC_Vertex_x", "MC_Vertex_y", "MC_Vertex_z", 
                "MC_Vertex_ntrk", "MC_Vertex_n",
                
                "MC_Vertex_PDG","MC_Vertex_PDGmother","MC_Vertex_PDGgmother",
                
                "Vertex_x", "Vertex_y", "Vertex_z",
                "Vertex_xErr", "Vertex_yErr", "Vertex_zErr",
                "Vertex_isPV", "Vertex_ntrk", "Vertex_chi2", "Vertex_n",
                "Vertex_thrust_angle", "Vertex_thrusthemis_emin", "Vertex_thrusthemis_emax",

                "Vertex_d2PV", "Vertex_d2PVx", "Vertex_d2PVy", "Vertex_d2PVz",
                "Vertex_d2PVErr", "Vertex_d2PVxErr", "Vertex_d2PVyErr", "Vertex_d2PVzErr",
                "Vertex_mass",
                "DV_d0","DV_z0",
                
                f"True{candidates}_vertex", f"True{candidates}_d0", f"True{candidates}_z0", 
                
                f"{candidates}Candidates_mass", 
                f"{candidates}Candidates_vertex", f"{candidates}Candidates_mcvertex", f"{candidates}Candidates_B",
                f"{candidates}Candidates_truth",
                f"{candidates}Candidates_px", f"{candidates}Candidates_py", f"{candidates}Candidates_pz", f"{candidates}Candidates_p", f"{candidates}Candidates_q",
                f"{candidates}Candidates_d0",  f"{candidates}Candidates_z0",f"{candidates}Candidates_anglethrust",
                
                f"{candidates}Candidates_h1px", f"{candidates}Candidates_h1py", f"{candidates}Candidates_h1pz",
                f"{candidates}Candidates_h1p", f"{candidates}Candidates_h1q", f"{candidates}Candidates_h1m", f"{candidates}Candidates_h1type",
                f"{candidates}Candidates_h1d0", f"{candidates}Candidates_h1z0",
                f"{candidates}Candidates_h2px", f"{candidates}Candidates_h2py", f"{candidates}Candidates_h2pz",
                f"{candidates}Candidates_h2p", f"{candidates}Candidates_h2q", f"{candidates}Candidates_h2m", f"{candidates}Candidates_h2type",
                f"{candidates}Candidates_h2d0", f"{candidates}Candidates_h2z0",
                ]
        if not training:
            desired_branches.append("EVT_MVA1")
        return desired_branches

Ideally I could also pass the decay argument to the processList to have flexibility on the inputs

@jsmiesko would wrapping the class in some way at least mean I could have a general stage1 script then wrappers for each mode that specify their decay, MC etc…? I’ll give it a go

Hi @aiwieder, since the process_list is outside of the class having decay argument will not be possible, but maybe we can put process_list inside of the class.

I will try to come up with the prototype PR tomorrow.

Best,
Juraj

1 Like

Hi @aiwieder,

I took the opportunity and rationalized the way how to write the analysis as a whole.
Please check PR #383, and let me know your thoughts.

Changes:

  • All configuration parameters were moved inside Analysis class.
  • The __init__() method gets a list of left over command line arguments.
  • All configuration parameters are now snake_case, as this is preffered by python linters.

Best,
Juraj

Hi @jsmiesko,

Yes this looks very nice. Thanks! I should have some time next week to get my stuff aligned with the preEDM branch for v0.9.0

Thanks,

Aidan

Hi @aiwieder,

the PR #383 have been merged into master and pre-edm4hep1 branches. Let me know if you find any issues.

Best,
Juraj

Hi @jsmiesko,

Sorry it took so long to come back to this. I’m giving it a go but keep getting unrecognised argument errors. Even in the higgs example.

[aiwieder@lxplus912 FCCAnalyses]$ fccanalysis run examples/FCCee/higgs/mH-recoil/mumu/analysis_stage1.py "--muon-pt 20 --test"
usage: fccanalysis [-h] [-v | -vv | -vvv] sub-command ...
fccanalysis: error: unrecognized arguments: --muon-pt 20

Should I not be calling it with fccanalysis run anymore?

Sorry for the noise, it would help if I had remembered to rebuild after rebasing :roll_eyes: Seems to work fine now