24        """Run the test fit"""
 
   26        testFile = tempfile.NamedTemporaryFile()
 
   28        main = basf2.create_path()
 
   30        ma.inputMdstList([basf2.find_file('B02JpsiKL_Jpsi2mumu.root', 'examples', False)], path=main)
 
   32        ma.fillParticleList('mu+:sig', 'muonID > 0.5', path=main)
 
   33        stdKlongs('allklm', path=main)
 
   35        ma.reconstructDecay('J/psi:mumu -> mu-:sig mu+:sig', '3.08 < M < 3.12', path=main)
 
   36        ma.reconstructMissingKlongDecayExpert('B0:sig -> J/psi:mumu K_L0:allklm', '',
 
   39        ma.matchMCTruth('B0:sig', path=main)
 
   42        main.add_module('TreeFitter',
 
   43                        particleList='B0:sig',
 
   45                        massConstraintList=[],
 
   47                        updateAllDaughters=True,
 
   48                        ignoreFromVertexFit='B0 -> J/psi ^K_L0')
 
   50        ntupler = basf2.register_module('VariablesToNtuple')
 
   51        ntupler.param('fileName', testFile.name)
 
   52        ntupler.param('variables', ['chiProb', 'isSignal', 'Mbc', 'deltaE', 'dz'])
 
   53        ntupler.param('particleList', 'B0:sig')
 
   54        main.add_module(ntupler)
 
   58        ntuplefile = TFile(testFile.name)
 
   59        ntuple = ntuplefile.Get('ntuple')
 
   61        self.assertFalse(ntuple.GetEntries() == 0, "Ntuple is empty.")
 
   63        allSig = ntuple.GetEntries("isSignal == 1")
 
   64        allBkg = ntuple.GetEntries("isSignal == 0")
 
   66        truePositives = ntuple.GetEntries("(chiProb > 0) && (isSignal == 1)")
 
   67        falsePositives = ntuple.GetEntries("(chiProb > 0) && (isSignal == 0)")
 
   69        SigDeltaEReasonable = ntuple.GetEntries("isSignal==1 && deltaE<0.1")
 
   71        print(f"True fit survivors: {truePositives} out of {allSig} true candidates")
 
   72        print(f"False fit survivors: {falsePositives} out of {allBkg} false candidates")
 
   74        self.assertTrue(falsePositives < 2041, "Background rejection too small.")
 
   75        self.assertTrue(truePositives > 522, "Signal rejection too high")
 
   77        print(f"Signal events with good deltaE values {SigDeltaEReasonable}")
 
   78        self.assertTrue(SigDeltaEReasonable > 463, "Signal kinematics is wrongly reconstructed too much")
 
   80        print("Test passed, cleaning up.")