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