gamma_vars = [] create_aliases_for_selected(['phi', 'theta', 'E', 'goodBelleGamma'], 'Sigma+ -> p+ [pi0 -> ^gamma ^gamma]', prefix = ['gamma1', 'gamma2']) # variables.addAlias('gamma_min_E', 'min(gamma1_E, gamma2_E)') # variables.addAlias('gamma_phi_diff', 'abs(formula(gamma1_phi - gamma2_phi))') # variables.addAlias('gamma_theta_diff', 'abs(formula(gamma1_theta - gamma2_theta))') # variables.addAlias('gamma_E_asym', 'abs(formula((gamma1_E - gamma2_E) / (gamma1_E + gamma2_E)))') # gamma_vars += ['gamma_min_E', 'gamma_phi_diff', 'gamma_theta_diff', 'gamma_E_asym', 'gamma1_theta', 'gamma2_theta', # 'gamma1_E', 'gamma2_E'] gamma_vars += ['gamma1_E', 'gamma2_E', 'gamma1_theta', 'gamma2_theta', 'genMotherPDG', 'isSignal'] ntuple_vars = sigma_vars + proton_vars + pi0_vars + gamma_vars + event_vars # RECONSTRUCTION # ============================================== ma.fillParticleList('p+:all', '', path = mp) # M Berger: standard pairwise PID > 0.6 and impact parameter > 0.003 ma.cutAndCopyList('p+:berger', 'p+:all', 'pid_ppi > 0.6 and pid_pk > 0.6 and dr > 0.003', path = mp) # M Berger: photons > 40 MeV and pi0 lab frame momentum > 100 MeV ma.cutAndCopyList('pi0:berger', 'pi0:mdst', 'daughter(0, E) > 0.04 and daughter(0, E) > 0.04 and p > 0.1', path = mp) ma.reconstructDecay('Sigma+:berger_loose -> p+:berger pi0:berger', 'M >= 1.0 and M <= 1.4', path = mp) # Set updateAllDaughters = True because the pi0:mdst list is mass constrained ma.vertexTree('Sigma+:berger_loose', 0, ipConstraint = True, updateAllDaughters = True, path = mp) # M Berger: discard condidates with wrong sign of flight distance ma.applyCuts('Sigma+:berger_loose', 'M >= 1.1 and M <= 1.3', path = mp) ma.matchMCTruth('Sigma+:berger_loose', path = mp) mp.add_module('VariablesToNtuple', particleList = 'Sigma+:berger_loose', variables=ntuple_vars, treeName='sigma_loose', fileName=sys.argv[2]) b2.process(path=mp) print(b2.statistics)
# create path main = b2.Path() # load input data from mdst/udst file filedirectory = '/gpfs/group/belle2/users/seemac/Kstll/signal/BtoKstjpsi/kst0jpsi' ma.inputMdstList( environmentType='default', filelist=[ f'{filedirectory}/mdst_000001_prod00012871_task10020000001.root' ], path=main) # fill final state particle lists impactcut = 'abs(d0)<2.0 and abs(z0)<5.0 ' ma.fillParticleList(decayString='e+:uncorrected', cut=impactcut + ' and electronID > 0.5', path=main) stdV0s.stdKshorts(path=main) # apply Bremsstrahlung correction to electrons variables.addAlias("goodFWDGamma", "passesCut(clusterReg == 1 and clusterE > 0.075)") variables.addAlias("goodBRLGamma", "passesCut(clusterReg == 2 and clusterE > 0.05)") variables.addAlias("goodBWDGamma", "passesCut(clusterReg == 3 and clusterE > 0.1)") variables.addAlias('goodGamma', 'passesCut(goodFWDGamma or goodBRLGamma or goodBWDGamma)') ma.fillParticleList('gamma:brems', 'goodGamma', path=main) ma.correctBrems('e+:corrected', 'e+:uncorrected', 'gamma:brems', path=main) variables.addAlias('isBremsCorrected', 'extraInfo(bremsCorrected)')
# create path my_path = b2.create_path() # load input ROOT file #ma.inputMdst(environmentType='default', # filename=b2.find_file('B2pi0D_D2hh_D2hhh_B2munu.root', 'examples', False), # path=my_path) my_path.add_module("RootInput", inputFileName='sim_recon.root') # print contents of the DataStore before loading Particles ma.printDataStore(path=my_path) # create and fill gamma/e/mu/pi/K/p ParticleLists # second argument are the selection criteria: '' means no cut, take all ma.fillParticleList(decayString='gamma:all', cut='', path=my_path) ma.fillParticleList(decayString='e-:all', cut='', path=my_path) ma.fillParticleList(decayString='mu-:all', cut='', path=my_path) ma.fillParticleList(decayString='pi-:all', cut='', path=my_path) ma.fillParticleList(decayString='K-:all', cut='', path=my_path) ma.fillParticleList(decayString='anti-p-:all', cut='', path=my_path) # alternatively, we can create and fill final state Particle lists only # with candidates that pass certain PID requirements ma.fillParticleList(decayString='gamma:highE', cut='E > 1.0', path=my_path) ma.fillParticleList(decayString='e+:good', cut='electronID > 0.1', path=my_path) ma.fillParticleList(decayString='mu+:good', cut='muonID > 0.1', path=my_path) ma.fillParticleList(decayString='pi+:good', cut='protonID > 0.1', path=my_path) ma.fillParticleList(decayString='K+:good', cut='kaonID > 0.1', path=my_path)
mp = b2.create_path() b2c.convertBelleMdstToBelleIIMdst(infile, path=mp) va.addAlias('cosa', 'cosAngleBetweenMomentumAndVertexVector') va.addAlias('cosaXY', 'cosAngleBetweenMomentumAndVertexVectorInXYPlane') va.addAlias('abs_dM', 'abs(dM)') va.addAlias('abs_dr', 'abs(dr)') va.addAlias('pid_ppi', 'atcPIDBelle(4,2)') va.addAlias('pid_pk', 'atcPIDBelle(4,3)') va.addAlias('pid_kpi', 'atcPIDBelle(3,2)') va.addAlias('ppi0_angle', 'daughterAngle(0, 1)') va.addAlias('p_decayAngle', 'decayAngle(0)') va.addAlias('pi0_decayAngle', 'decayAngle(1)') ma.fillParticleList('p+:good', 'pid_ppi > 0.6 and pid_pk > 0.6', path=mp) # ma.vertexTree('pi0:mdst', ipConstraint = True, massConstraint = ['pi0'], path = mp) ma.reconstructDecay('Sigma+:std -> p+:good pi0:mdst', '1.1 < M < 1.3', path=mp) ma.vertexTree('Sigma+:std', 0, ipConstraint=True, updateAllDaughters=True, path=mp) # Select good pi0 based on mass and gamma energy ma.applyCuts( 'Sigma+:std', 'daughter(1, daughter(0, E)) > 0.04 and daughter(1, daughter(1, E)) > 0.04 and daughter(1, abs(dM)) < 0.02', path=mp) ma.vertexTree('Sigma+:std',
def reconstruction(input_file, output_file): my_path = b2.create_path() ma.inputMdst("default", input_file, my_path) # Find decay name from the input file name decay_name = "_".join(input_file.split("/")[-1].split("_")[0:2]) # Load configuration file config = yaml.safe_load(open("config/reco_config.yaml")) options = config[decay_name] # Parse list of subdecays in decay chain decays = options["sub_decays"] decays = DecayList(decays) # Create particle lists for final state particles fsps = decays.get_fsps() for particle in fsps: ma.fillParticleList(particle, "", path=my_path) # Reconstruct requested decay chains for decay in decays: ma.reconstructDecay(str(decay), "", path=my_path) # Perform truth matching for requested particles truth_match_particles = decays.mothers for truth_match_particle in truth_match_particles: ma.looseMCTruth(truth_match_particle, path=my_path) # Perform vertex fitting head = decays.get_head() vtx_decay_string = decays.get_chain() print(vtx_decay_string) vx.vertexRave(head, 0, vtx_decay_string, constraint="iptube", path=my_path) # ma.rankByLowest("B0", 'chiProb', numBest=3, outputVariable='B_vtx_rank', path=my_path) # ma.variables.addAlias('B_vtx_rank', 'extraInfo(B_vtx_rank)') ma.buildRestOfEvent(head, path=my_path) # Tag-side vx.TagV(head, "breco", 0.001, path=my_path) ma.buildEventKinematics(path=my_path) ma.buildEventShape(path=my_path) # Create centre-of-mass frame variables cms_kinematics = vu.create_aliases( vc.kinematics, "useCMSFrame({variable})", prefix="CMS" ) variables = [ item for sublist in [ vc.kinematics, cms_kinematics, vc.deltae_mbc, vc.inv_mass, vc.event_shape, vc.vertex, vc.mc_truth, vc.mc_kinematics, vc.mc_vertex, vc.mc_tag_vertex, ] for item in sublist ] trees = yaml.safe_load(open("config/tree_names.yaml")) for particle in decays.all_particles: ma.variablesToNtuple( particle, variables, filename=output_file, treename=trees[particle], path=my_path, ) b2.process(my_path) print(b2.statistics)
import basf2 as b2 import modularAnalysis as ma import variables.collections as vc import variables.utils as vu import stdCharged as stdc # create path my_path = b2.create_path() # load input ROOT file ma.inputMdst(environmentType='default', filename=b2.find_file('B2rhogamma_rho2pipi.root', 'examples', False), path=my_path) ma.fillParticleList(decayString='gamma:highE', cut='E > 1.5', path=my_path) ma.fillParticleList(decayString='pi+:loose', cut='abs(d0) < 0.5 and abs(z0) < 0.5 and pionID > 0.002', path=my_path) # reconstruct rho -> pi+ pi- decay # keep only candidates with 0.6 < M(pi+pi-) < 1.0 GeV ma.reconstructDecay(decayString='rho0 -> pi+:loose pi-:loose', cut='0.6 < M < 1.0', path=my_path) # reconstruct B0 -> rho0 gamma decay # keep only candidates with Mbc > 5.2 GeV # and -2 < Delta E < 2 GeV ma.reconstructDecay(decayString='B0 -> rho0 gamma:highE', cut='5.2 < Mbc and abs(deltaE) < 2.0',
# create path main = b2.Path() # load input data from mdst/udst file filedirectory = '/gpfs/group/belle2/users/seemac/Kstll/signal/BtoKstjpsi/kst0jpsi' ma.inputMdstList( environmentType='default', filelist=[ f'{filedirectory}/mdst_000001_prod00012871_task10020000001.root' ], path=main) # fill final state particle lists impactcut = 'abs(d0)<2.0 and abs(z0)<5.0 ' ma.fillParticleList(decayString='mu+:all', cut=impactcut + ' and muonID > 0.5', path=main) stdV0s.stdKshorts(path=main) # combine final state particles to form composite particles ma.reconstructDecay('J/psi:mumu -> mu+:all mu-:all', cut='dM < 0.11', path=main) # perform vertex fit of J/psi candidates vertex.KFit('J/psi:mumu', conf_level=0.0, path=main) # combine J/psi and KS candidates to form B0 candidates ma.reconstructDecay('B0 -> J/psi:mumu K_S0:merged', cut='Mbc > 5.2 and abs(deltaE) < 0.3', path=main)
def reconstruct(infile='default.root', outfile='output_beta.root', path=None): """ Args: infile: Input file name (use overwrite from basf2) outfile: output file name (use overwrite from basf2) path: (optional) basf2 path Returns: path """ setup() # EXAMPE RECONSTRUCTION CODE # DELETE OR MODIFY FROM HERE just_an_example = True if just_an_example: with open(outfile, 'w') as f: f.write("Proccessed example input " + infile) else: path = b2.create_path() if path is None else path # Input file ma.inputMdstList("default", infile, path=path) # Event level cuts examples ma.applyEventCuts('R2EventLevel<0.6 and nTracks>=3', path=path) # # Load Primary particles # from stdPhotons import stdPhotons stdPhotons('cdc', path) ma.cutAndCopyList('gamma:sig', 'gamma:cdc', 'clusterNHits > 1.5 and E > 1.5', True, path) from stdPi0s import stdPi0s stdPi0s('eff20', path) # Loading charged tracks good_track = 'thetaInCDCAcceptance and nCDCHits>20 and dr < 0.5 and abs(dz) < 2' ma.fillParticleList("pi+:sig", good_track + " and pionID > 0.0", path=path) ma.fillParticleList("K+:sig", good_track + " and kaonID > 0.0", path=path) # # Combine particles # ma.reconstructDecay('K*0:sig -> K+:sig pi-:sig', '0.6 < M < 1.6', path=path) ma.reconstructDecay('B0:sig -> K*0:sig gamma:sig', '5.22 < Mbc < 5.3 and abs(deltaE)< 1', path=path) # Final Calculateions ma.rankByHighest("B0:ch1", "formula(-1*abs(deltaE))", outputVariable='Rank_deltaE', path=path) ma.buildEventShape(allMoments=True, path=path) ma.matchMCTruth("B0:sig", path=path) # # Write out Ntuples # all_vars = get_variables() ma.variablesToNtuple('B0:ch1', all_vars, filename=outfile, treename="B0", path=path) # TO HERE #ma.printMCParticles(path=path) return path
from modularAnalysis import reconstructDecay from modularAnalysis import copyLists from modularAnalysis import variablesToNtuple from variables import variables # create path mypath = b2.create_path() # load input ROOT file inputMdst(environmentType='default', filename=b2.find_file('B2pi0D_D2hh_D2hhh_B2munu_evtgen.root', 'examples', False), path=mypath) # fill an all photon and all charged particle (does not really matter which one) list # clusterE: Returns ECL cluster's energy corrected for leakage and background fillParticleList('gamma:all', 'clusterE > 0.1', path=mypath) # neutral clusters fillParticleList('e-:all', 'clusterE > 0.1', path=mypath) # track matched clusters # reconstruct a pseudo particles with different combinations (implicit charge conjugation) reconstructDecay('vpho:1 -> gamma:all gamma:all', '', 1, path=mypath) # two neutral '00' reconstructDecay('vpho:2 -> gamma:all e-:all', '', 2, path=mypath) # neutral and charged '0+' and '0-' reconstructDecay('vpho:3 -> e-:all e+:all', '', 3, path=mypath) # different charge '+-' and '-+' reconstructDecay('vpho:4 -> e-:all e-:all', '', 4, path=mypath) # same charge '++' and '--' copyLists('vpho:bhabha', ['vpho:1', 'vpho:2', 'vpho:3', 'vpho:4'], path=mypath) # aliases to make output better readable variables.addAlias('combinationID', 'extraInfo(decayModeID)') variables.addAlias('deltaPhi', 'daughterDiffOfClusterPhi(0, 1)') variables.addAlias('deltaTheta', 'formula(daughter(0, clusterTheta) - daughter(1, clusterTheta))') variables.addAlias('charge_0', 'daughter(0, charge)') variables.addAlias('charge_1', 'daughter(1, charge)')
elif step == 'qqbar': input_file = [path + '*bar_expert/*'] else: sys.exit( 'Step does not match any of the available samples: `signal` or `qqbar`' ) outfile = 'MVAExpert_fullNTuple_' + step + '.root' # --------------------------------------------------------------------------------------------- # Perform analysis. main = b2.create_path() ma.inputMdst(environmentType='default', filename=input_file, path=main) ma.fillParticleList(decayString='gamma:all', cut='', path=main) ma.fillParticleList(decayString='pi+:good', cut='chiProb > 0.001 and pionID > 0.5', path=main) ma.fillParticleList(decayString='pi-:good', cut='chiProb > 0.001 and pionID > 0.5', path=main) ma.reconstructDecay(decayString='K_S0 -> pi+:good pi-:good', cut='0.480<=M<=0.516', dmID=1, path=main) ma.reconstructDecay(decayString='pi0 -> gamma:all gamma:all', cut='0.115<=M<=0.152', dmID=1, path=main)
my_path = b2.create_path() # load input ROOT file ma.inputMdst(environmentType='default', filename=b2.find_file('B2JPsipi0_JPsi2mumu.root', 'examples', False), path=my_path) # use standard final state particle lists # # creates "pi0:looseFit" ParticleList # https://confluence.desy.de/display/BI/Physics+StandardParticles stdPi0s(listtype='looseFit', path=my_path) # creates "highPID" ParticleLists (and c.c.) ma.fillParticleList(decayString='mu+:highPID', cut='muonID > 0.2 and d0 < 2 and abs(z0) < 4', path=my_path) # reconstruct J/psi -> mu+ mu- decay # keep only candidates with dM<0.11 ma.reconstructDecay(decayString='J/psi:mumu -> mu+:highPID mu-:highPID', cut='dM<0.11 and 3.07 < M < 3.11', path=my_path) # reconstruct B0 -> J/psi Ks decay # keep only candidates with Mbc > 5.1 and abs(deltaE)<0.15 ma.reconstructDecay(decayString='B0:jspipi0 -> J/psi:mumu pi0:looseFit', cut='Mbc > 5.1 and abs(deltaE)<0.15', path=my_path) vx.vertexTree(
import basf2 as b2 import modularAnalysis as ma import variables.collections as vc import variables.utils as vu # create path my_path = b2.create_path() # load input ROOT file ma.inputMdst(environmentType='default', filename=b2.find_file('JPsi2ee_e2egamma.root', 'examples', False), path=my_path) # fill particleLists ma.fillParticleList(decayString='e+:uncorrected', cut='electronID > 0.2 and d0 < 2 and abs(z0) < 4', path=my_path) ma.fillParticleList(decayString='gamma:all', cut='E < 1.0', writeOut=False, path=my_path) # loose mc matching (recommended) ma.looseMCTruth(list_name='e+:uncorrected', path=my_path) ma.looseMCTruth(list_name='gamma:all', path=my_path) # fsr correction ma.correctFSR(outputListName='e+:corrected', inputListName='e+:uncorrected', gammaListName='gamma:all', angleThreshold=5.0,
if not os.path.isfile('reco.root'): sys.exit( 'Required input file (B2A101-Y4SEventGeneration-gsim-BKGx0.root) does not exist. ' 'Please run B2A101-Y4SEventGeneration.py and B2A103-SimulateAndReconstruct-withoutBeamBkg.py ' 'tutorial scripts first.') # load input ROOT file inputMdst('default', 'reco.root') # print contents of the DataStore before loading Particles printDataStore() # create and fill gamma/e/mu/pi/K/p ParticleLists # second argument are the selection criteria: '' means no cut, take all # fillParticleList('gamma:all', '') fillParticleList('e-:all', '') fillParticleList('mu-:all', '') fillParticleList('pi-:all', '') fillParticleList('K-:all', '') fillParticleList('anti-p-:all', '') # alternatively, we can create and fill final state Particle lists only # with candidates that pass certain PID requirements fillParticleList('gamma:highE', 'E > 1.0') fillParticleList('e+:good', 'eid > 0.1') fillParticleList('mu+:good', 'muid > 0.1') fillParticleList('pi+:good', 'piid > 0.1') fillParticleList('K+:good', 'Kid > 0.1') fillParticleList('p+:good', 'prid > 0.1') # another possibility is to use default functions