# Support for command line arguments

**URL:** <https://fccsw-forum.web.cern.ch/t/support-for-command-line-arguments/218>\
**Category:** Analysis\
**Created:** [June 12, 2024, 1:47pm UTC](https://fccsw-forum.web.cern.ch/t/support-for-command-line-arguments/218 "2024-06-12T13:47:00Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![aiwieder](https://fccsw-forum.web.cern.ch/letter_avatar_proxy/v4/letter/a/dfb087/32.png) [@aiwieder](https://fccsw-forum.web.cern.ch/u/aiwieder)\
**Post date:** [June 12, 2024, 1:47pm UTC](https://fccsw-forum.web.cern.ch/t/support-for-command-line-arguments/218/1 "2024-06-12T13:47:00Z")

</div>

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](https://hep-fcc.github.io/FCCAnalyses/man/latest/fccanalysis-run.html) it seems like the answer is no. Would there be interest in having this added? Not that I know how that would be done 😉

Thanks for any help,

Aidan

---

<div class="post-metadata">

**Author:** ![jsmiesko](https://fccsw-forum.web.cern.ch/user_avatar/fccsw-forum.web.cern.ch/jsmiesko/32/38_2.png) [@jsmiesko](https://fccsw-forum.web.cern.ch/u/jsmiesko)\
**Post date:** [June 12, 2024, 10:21pm UTC](https://fccsw-forum.web.cern.ch/t/support-for-command-line-arguments/218/2 "2024-06-12T22:21:59Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![aiwieder](https://fccsw-forum.web.cern.ch/letter_avatar_proxy/v4/letter/a/dfb087/32.png) [@aiwieder](https://fccsw-forum.web.cern.ch/u/aiwieder)\
**Post date:** [June 13, 2024, 9:29am UTC](https://fccsw-forum.web.cern.ch/t/support-for-command-line-arguments/218/3 "2024-06-13T09:29:08Z")

</div>

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

```python
#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

```

---

<div class="post-metadata">

**Author:** ![aiwieder](https://fccsw-forum.web.cern.ch/letter_avatar_proxy/v4/letter/a/dfb087/32.png) [@aiwieder](https://fccsw-forum.web.cern.ch/u/aiwieder)\
**Post date:** [June 13, 2024, 9:31am UTC](https://fccsw-forum.web.cern.ch/t/support-for-command-line-arguments/218/4 "2024-06-13T09:31:12Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![aiwieder](https://fccsw-forum.web.cern.ch/letter_avatar_proxy/v4/letter/a/dfb087/32.png) [@aiwieder](https://fccsw-forum.web.cern.ch/u/aiwieder)\
**Post date:** [June 13, 2024, 2:15pm UTC](https://fccsw-forum.web.cern.ch/t/support-for-command-line-arguments/218/5 "2024-06-13T14:15:08Z")

</div>

@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

---

<div class="post-metadata">

**Author:** ![jsmiesko](https://fccsw-forum.web.cern.ch/user_avatar/fccsw-forum.web.cern.ch/jsmiesko/32/38_2.png) [@jsmiesko](https://fccsw-forum.web.cern.ch/u/jsmiesko)\
**Post date:** [June 24, 2024, 6:19pm UTC](https://fccsw-forum.web.cern.ch/t/support-for-command-line-arguments/218/6 "2024-06-24T18:19:22Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![jsmiesko](https://fccsw-forum.web.cern.ch/user_avatar/fccsw-forum.web.cern.ch/jsmiesko/32/38_2.png) [@jsmiesko](https://fccsw-forum.web.cern.ch/u/jsmiesko)\
**Post date:** [June 28, 2024, 11:28am UTC](https://fccsw-forum.web.cern.ch/t/support-for-command-line-arguments/218/7 "2024-06-28T11:28:49Z")

</div>

Hi @aiwieder,

I took the opportunity and rationalized the way how to write the analysis as a whole.  
Please check PR [#383](https://github.com/HEP-FCC/FCCAnalyses/pull/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

---

<div class="post-metadata">

**Author:** ![aiwieder](https://fccsw-forum.web.cern.ch/letter_avatar_proxy/v4/letter/a/dfb087/32.png) [@aiwieder](https://fccsw-forum.web.cern.ch/u/aiwieder)\
**Post date:** [June 28, 2024, 1:59pm UTC](https://fccsw-forum.web.cern.ch/t/support-for-command-line-arguments/218/8 "2024-06-28T13:59:50Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![jsmiesko](https://fccsw-forum.web.cern.ch/user_avatar/fccsw-forum.web.cern.ch/jsmiesko/32/38_2.png) [@jsmiesko](https://fccsw-forum.web.cern.ch/u/jsmiesko)\
**Post date:** [July 5, 2024, 1:12pm UTC](https://fccsw-forum.web.cern.ch/t/support-for-command-line-arguments/218/9 "2024-07-05T13:12:41Z")

</div>

Hi @aiwieder,

the PR [#383](https://github.com/HEP-FCC/FCCAnalyses/pull/383) have been merged into `master` and `pre-edm4hep1` branches. Let me know if you find any issues.

Best,  
Juraj

---

<div class="post-metadata">

**Author:** ![aiwieder](https://fccsw-forum.web.cern.ch/letter_avatar_proxy/v4/letter/a/dfb087/32.png) [@aiwieder](https://fccsw-forum.web.cern.ch/u/aiwieder)\
**Post date:** [August 14, 2024, 12:18pm UTC](https://fccsw-forum.web.cern.ch/t/support-for-command-line-arguments/218/10 "2024-08-14T12:18:37Z")

</div>

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.

```bash
[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?

---

<div class="post-metadata">

**Author:** ![aiwieder](https://fccsw-forum.web.cern.ch/letter_avatar_proxy/v4/letter/a/dfb087/32.png) [@aiwieder](https://fccsw-forum.web.cern.ch/u/aiwieder)\
**Post date:** [August 14, 2024, 12:50pm UTC](https://fccsw-forum.web.cern.ch/t/support-for-command-line-arguments/218/11 "2024-08-14T12:50:25Z")

</div>

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