536 def reconstruct(self) -> pybasf2.Path:
537 """
538 Returns pybasf2.Path which reconstructs the particles and does the vertex fitting if necessary
539 """
540 import ROOT
541 path = basf2.create_path()
542
543 for particle in self.particles:
544 for channel in particle.channels:
545 expert = basf2.register_module('MVAExpert')
546 expert.set_name(f'MVAExpert_{channel.name}')
547 if self.config.training:
548 expert.param('identifier', f'{channel.label}.xml')
549 else:
550 expert.param('identifier', f'{self.config.prefix}_{channel.label}')
551 expert.param('extraInfoName', 'SignalProbability')
552 expert.param('listNames', [channel.name])
553
554 expert.set_log_level(basf2.logging.log_level.ERROR)
555 path.add_module(expert)
556
557 if self.config.monitor:
558 if self.config.monitor == 'simple':
559 hist_variables = [channel.mvaConfig.target, 'extraInfo(decayModeID)']
560 hist_variables_2d = [(channel.mvaConfig.target, 'extraInfo(decayModeID)')]
561 else:
562 hist_variables = ['mcErrors',
563 'mcParticleStatus',
564 'extraInfo(SignalProbability)',
565 channel.mvaConfig.target,
566 'extraInfo(decayModeID)'] + list(channel.mvaConfig.spectators.keys())
567 hist_variables_2d = [('extraInfo(SignalProbability)', channel.mvaConfig.target),
568 ('extraInfo(SignalProbability)', 'mcErrors'),
569 ('extraInfo(SignalProbability)', 'mcParticleStatus'),
570 ('extraInfo(decayModeID)', channel.mvaConfig.target),
571 ('extraInfo(decayModeID)', 'mcErrors'),
572 ('extraInfo(decayModeID)', 'mcParticleStatus')]
573 for specVar in channel.mvaConfig.spectators:
574 hist_variables_2d.append(('extraInfo(SignalProbability)', specVar))
575 hist_variables_2d.append(('extraInfo(decayModeID)', specVar))
576 hist_variables_2d.append((channel.mvaConfig.target, specVar))
577 filename = os.path.join(self.config.monitoring_path, 'Monitor_PostReconstruction_AfterMVA.root')
578 ma.variablesToHistogram(
579 channel.name,
580 variables=config.variables2binnings(hist_variables),
581 variables_2d=config.variables2binnings_2d(hist_variables_2d),
582 filename=filename,
583 ignoreCommandLineOverride=True,
584 directory=f'{channel.label}',
585 path=path)
586
587 cutstring = ''
588 if particle.postCutConfig.value > 0.0:
589 cutstring = f'{particle.postCutConfig.value} < extraInfo(SignalProbability)'
590
591 ma.mergeListsWithBestDuplicate(particle.identifier, [c.name for c in particle.channels],
592 variable='particleSource', writeOut=True, path=path)
593
594 if self.config.monitor:
595 if self.config.monitor == 'simple':
596 hist_variables = [particle.mvaConfig.target, 'extraInfo(decayModeID)']
597 hist_variables_2d = [(particle.mvaConfig.target, 'extraInfo(decayModeID)')]
598 else:
599 hist_variables = ['mcErrors',
600 'mcParticleStatus',
601 'extraInfo(SignalProbability)',
602 particle.mvaConfig.target,
603 'extraInfo(decayModeID)'] + list(particle.mvaConfig.spectators.keys())
604 hist_variables_2d = [('extraInfo(decayModeID)', particle.mvaConfig.target),
605 ('extraInfo(decayModeID)', 'mcErrors'),
606 ('extraInfo(decayModeID)', 'mcParticleStatus')]
607 for specVar in particle.mvaConfig.spectators:
608 hist_variables_2d.append(('extraInfo(SignalProbability)', specVar))
609 hist_variables_2d.append(('extraInfo(decayModeID)', specVar))
610 hist_variables_2d.append((particle.mvaConfig.target, specVar))
611 filename = os.path.join(self.config.monitoring_path, 'Monitor_PostReconstruction_BeforePostCut.root')
612 ma.variablesToHistogram(
613 particle.identifier,
614 variables=config.variables2binnings(hist_variables),
615 variables_2d=config.variables2binnings_2d(hist_variables_2d),
616 filename=filename,
617 ignoreCommandLineOverride=True,
618 directory=config.removeJPsiSlash(f'{particle.identifier}'),
619 path=path)
620
621 ma.applyCuts(particle.identifier, cutstring, path=path)
622
623 if self.config.monitor:
624 filename = os.path.join(self.config.monitoring_path, 'Monitor_PostReconstruction_BeforeRanking.root')
625 ma.variablesToHistogram(
626 particle.identifier,
627 variables=config.variables2binnings(hist_variables),
628 variables_2d=config.variables2binnings_2d(hist_variables_2d),
629 filename=filename,
630 ignoreCommandLineOverride=True,
631 directory=config.removeJPsiSlash(f'{particle.identifier}'),
632 path=path)
633
634 ma.rankByHighest(particle.identifier, 'extraInfo(SignalProbability)',
635 particle.postCutConfig.bestCandidateCut, 'postCut_rank', path=path)
636
637 uniqueSignal = basf2.register_module('TagUniqueSignal')
638 uniqueSignal.param('particleList', particle.identifier)
639 uniqueSignal.param('target', particle.mvaConfig.target)
640 uniqueSignal.param('extraInfoName', 'uniqueSignal')
641 uniqueSignal.set_name(f'TagUniqueSignal_{particle.identifier}')
642
643 uniqueSignal.set_log_level(basf2.logging.log_level.ERROR)
644 path.add_module(uniqueSignal)
645
646 if self.config.monitor:
647 if self.config.monitor != 'simple':
648 hist_variables += ['extraInfo(postCut_rank)']
649 hist_variables_2d += [('extraInfo(decayModeID)', 'extraInfo(postCut_rank)'),
650 (particle.mvaConfig.target, 'extraInfo(postCut_rank)'),
651 ('mcErrors', 'extraInfo(postCut_rank)'),
652 ('mcParticleStatus', 'extraInfo(postCut_rank)')]
653 for specVar in particle.mvaConfig.spectators:
654 hist_variables_2d.append(('extraInfo(postCut_rank)', specVar))
655 filename = os.path.join(self.config.monitoring_path, 'Monitor_PostReconstruction_AfterRanking.root')
656 ma.variablesToHistogram(
657 particle.identifier,
658 variables=config.variables2binnings(hist_variables),
659 variables_2d=config.variables2binnings_2d(hist_variables_2d),
660 filename=filename,
661 ignoreCommandLineOverride=True,
662 directory=config.removeJPsiSlash(f'{particle.identifier}'),
663 path=path)
664
665 filename = os.path.join(self.config.monitoring_path, 'Monitor_Final.root')
666 if self.config.monitor == 'simple':
667 hist_variables = ['extraInfo(uniqueSignal)', 'extraInfo(decayModeID)']
668 hist_variables_2d = [('extraInfo(uniqueSignal)', 'extraInfo(decayModeID)')]
669 ma.variablesToHistogram(
670 particle.identifier,
671 variables=config.variables2binnings(hist_variables),
672 variables_2d=config.variables2binnings_2d(hist_variables_2d),
673 filename=filename,
674 ignoreCommandLineOverride=True,
675 directory=config.removeJPsiSlash(f'{particle.identifier}'),
676 path=path)
677 else:
678 variables = ['extraInfo(SignalProbability)', 'mcErrors', 'mcParticleStatus', particle.mvaConfig.target,
679 'extraInfo(uniqueSignal)', 'extraInfo(decayModeID)'] + list(particle.mvaConfig.spectators.keys())
680
681 ma.variablesToNtuple(
682 particle.identifier,
683 variables,
684 treename=ROOT.Belle2.MakeROOTCompatible.makeROOTCompatible(
685 config.removeJPsiSlash(f'{particle.identifier} variables')),
686 filename=filename,
687 ignoreCommandLineOverride=True,
688 path=path)
689 return path
690
691