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