Belle II Software light-2607-kasei
Teacher Class Reference

Public Member Functions

 __init__ (self, typing.Sequence[config.Particle] particles, config.FeiConfiguration config)
 
 upload (self, str channel)
 
 do_all_trainings (self)
 

Static Public Member Functions

 create_fake_weightfile (str channel)
 
 check_if_weightfile_is_fake (str filename)
 

Public Attributes

 particles = particles
 list of config.Particle objects
 
 config = config
 config.FeiConfiguration object
 

Static Public Attributes

 MaximumNumberOfMVASamples = int(1e7)
 Maximum number of events per class, the sampling rates are chosen so that the training data does not exceed this number.
 
 MinimumNumberOfMVASamples = int(5e2)
 Minimum number of events per class if the training data contains less events the channel is not used due to low statistics.
 

Detailed Description

Performs all necessary trainings for all training data files which are
available but where there is no weight file available yet.
This class is usually used by the do_trainings function below, to perform the necessary trainings after each stage.
The trainings are run in parallel using multi-threading of python.
Each training is done by a subprocess call, the training command (passed by config.externTeacher) can be either
  * basf2_mva_teacher, the training will be done directly on the machine
  * externClustTeacher, the training will be submitted to the batch system of KEKCC

Definition at line 692 of file core.py.

Constructor & Destructor Documentation

◆ __init__()

__init__ ( self,
typing.Sequence[config.Particle] particles,
config.FeiConfiguration config )
Create a new Teacher object
@param particles list of config.Particle objects
@param config config.FeiConfiguration object

Definition at line 709 of file core.py.

709 def __init__(self, particles: typing.Sequence[config.Particle], config: config.FeiConfiguration):
710 """
711 Create a new Teacher object
712 @param particles list of config.Particle objects
713 @param config config.FeiConfiguration object
714 """
715
716 self.particles = particles
717
718 self.config = config
719

Member Function Documentation

◆ check_if_weightfile_is_fake()

check_if_weightfile_is_fake ( str filename)
static
Checks if the provided filename is a fake-weight file or not
@param filename the filename of the weight file

Definition at line 748 of file core.py.

748 def check_if_weightfile_is_fake(filename: str):
749 """
750 Checks if the provided filename is a fake-weight file or not
751 @param filename the filename of the weight file
752 """
753 try:
754 return '<method>Trivial</method>' in open(filename).readlines()[2]
755 except BaseException:
756 return True
757 return True
758

◆ create_fake_weightfile()

create_fake_weightfile ( str channel)
static
Create a fake weight file using the trivial method, it will always return 0.0
@param channel for which we create a fake weight file

Definition at line 721 of file core.py.

721 def create_fake_weightfile(channel: str):
722 """
723 Create a fake weight file using the trivial method, it will always return 0.0
724 @param channel for which we create a fake weight file
725 """
726 content = f"""
727 <?xml version="1.0" encoding="utf-8"?>
728 <method>Trivial</method>
729 <weightfile>{channel}.xml</weightfile>
730 <treename>tree</treename>
731 <target_variable>isSignal</target_variable>
732 <weight_variable>__weight__</weight_variable>
733 <signal_class>1</signal_class>
734 <max_events>0</max_events>
735 <number_feature_variables>1</number_feature_variables>
736 <variable0>M</variable0>
737 <number_spectator_variables>0</number_spectator_variables>
738 <number_data_files>1</number_data_files>
739 <datafile0>train.root</datafile0>
740 <Trivial_version>1</Trivial_version>
741 <Trivial_output>0</Trivial_output>
742 <signal_fraction>0.066082567</signal_fraction>
743 """
744 with open(f'{channel}.xml', "w") as f:
745 f.write(content)
746

◆ do_all_trainings()

do_all_trainings ( self)
Do all trainings for which we find training data

Definition at line 770 of file core.py.

770 def do_all_trainings(self):
771 """
772 Do all trainings for which we find training data
773 """
774 # Always avoid the top-level 'import ROOT'.
775 import ROOT # noqa
776 # FEI uses multi-threading for parallel execution of tasks therefore
777 # the ROOT gui-thread is disabled, which otherwise interferes sometimes
778 ROOT.PyConfig.StartGuiThread = False
779 job_list = []
780
781 all_stage_particles = get_stages_from_particles(self.particles)
782 if self.config.cache is None:
783 stagesToTrain = range(1, len(all_stage_particles)+1)
784 else:
785 stagesToTrain = [self.config.cache]
786
787 filename = 'training_input.root'
788 if os.path.isfile(filename):
789 f = ROOT.TFile.Open(filename, 'read')
790 if f.IsZombie():
791 B2WARNING(f'Training of MVC failed: {filename}. ROOT file corrupt. No weight files will be provided.')
792 elif len([k.GetName() for k in f.GetListOfKeys()]) == 0:
793 B2WARNING(
794 f'Training of MVC failed: {filename}. ROOT file has no trees. No weight files will be provided.')
795 else:
796 for istage in stagesToTrain:
797 for particle in all_stage_particles[istage-1]:
798 for channel in particle.channels:
799 weightfile = f'{channel.label}.xml'
800 if basf2_mva.available(weightfile):
801 B2INFO(f"FEI-core: Skipping {weightfile}, already available")
802 continue
803 else:
804 treeName = ROOT.Belle2.MakeROOTCompatible.makeROOTCompatible(f'{channel.label} variables')
805 keys = [m for m in f.GetListOfKeys() if treeName in m.GetName()]
806 if not keys:
807 B2WARNING("Training of MVC failed. "
808 f"Couldn't find tree for channel {channel}. Ignoring channel.")
809 continue
810 elif len(keys) > 1:
811 B2WARNING(f"Found more than one tree for channel {channel}. Taking first tree from: {keys}")
812 tree = keys[0].ReadObj()
813 total_entries = tree.GetEntries()
814 nSig = tree.GetEntries(f'{channel.mvaConfig.target}==1.0')
815 nBg = tree.GetEntries(f'{channel.mvaConfig.target}==0.0')
816 B2INFO(
817 f'FEI-core: Number of events for channel: {channel.label}, '
818 f'Total: {total_entries}, Signal: {nSig}, Background: {nBg}')
819 if nSig < Teacher.MinimumNumberOfMVASamples:
820 B2WARNING("Training of MVC failed. "
821 f"Tree contains too few signal events {nSig}. Ignoring channel {channel}.")
822 self.create_fake_weightfile(channel.label)
823 self.upload(channel.label)
824 continue
825 if nBg < Teacher.MinimumNumberOfMVASamples:
826 B2WARNING("Training of MVC failed. "
827 f"Tree contains too few bckgrd events {nBg}. Ignoring channel {channel}.")
828 self.create_fake_weightfile(channel.label)
829 self.upload(channel.label)
830 continue
831 variable_str = "' '".join(channel.mvaConfig.variables)
832
833 spectators = list(channel.mvaConfig.spectators.keys())
834 if channel.mvaConfig.sPlotVariable is not None:
835 spectators.append(channel.mvaConfig.sPlotVariable)
836 spectators_str = "' '".join(spectators)
837
838 treeName = ROOT.Belle2.MakeROOTCompatible.makeROOTCompatible(f'{channel.label} variables')
839 command = (f"{self.config.externTeacher}"
840 f" --method '{channel.mvaConfig.method}'"
841 f" --target_variable '{channel.mvaConfig.target}'"
842 f" --treename '{treeName}'"
843 f" --datafile 'training_input.root'"
844 f" --signal_class 1"
845 f" --variables '{variable_str}'"
846 f" --identifier '{weightfile}'")
847 if len(spectators) > 0:
848 command += f" --spectators '{spectators_str}'"
849 command += f" {channel.mvaConfig.config} > '{channel.label}'.log 2>&1"
850 B2INFO(f"Used following command to invoke teacher: \n {command}")
851 job_list.append((channel.label, command))
852 f.Close()
853
854 if len(job_list) > 0:
855 p = multiprocessing.Pool(None, maxtasksperchild=1)
856 func = functools.partial(subprocess.call, shell=True)
857 p.map(func, [c for _, c in job_list])
858 p.close()
859 p.join()
860 weightfiles = []
861 for name, _ in job_list:
862 if not basf2_mva.available(f'{name}.xml'):
863 B2WARNING("Training of MVC failed. For unknown reasons, check the logfile", f'{name}.log')
864 self.create_fake_weightfile(name)
865 weightfiles.append(self.upload(name))
866 return weightfiles
867
868

◆ upload()

upload ( self,
str channel )
Upload the weight file into the condition database
@param channel whose weight file is uploaded

Definition at line 759 of file core.py.

759 def upload(self, channel: str):
760 """
761 Upload the weight file into the condition database
762 @param channel whose weight file is uploaded
763 """
764 disk = f'{channel}.xml'
765 dbase = f'{self.config.prefix}_{channel}'
766 basf2_mva.upload(disk, dbase)
767 print(f"FEI-core: Uploading {dbase} to localdb")
768 return (disk, dbase)
769

Member Data Documentation

◆ config

config = config

config.FeiConfiguration object

Definition at line 718 of file core.py.

◆ MaximumNumberOfMVASamples

MaximumNumberOfMVASamples = int(1e7)
static

Maximum number of events per class, the sampling rates are chosen so that the training data does not exceed this number.

Definition at line 704 of file core.py.

◆ MinimumNumberOfMVASamples

MinimumNumberOfMVASamples = int(5e2)
static

Minimum number of events per class if the training data contains less events the channel is not used due to low statistics.

Definition at line 707 of file core.py.

◆ particles

particles = particles

list of config.Particle objects

Definition at line 716 of file core.py.


The documentation for this class was generated from the following file: