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