Belle II Software development
MVAExpert.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8#include <tracking/trackingUtilities/mva/MVAExpert.h>
9
11#include <mva/dataobjects/DatabaseRepresentationOfWeightfile.h>
12#include <mva/interface/Expert.h>
13#include <mva/interface/Weightfile.h>
14#include <framework/database/DBObjPtr.h>
15
16namespace Belle2 {
22 namespace MVA {
23 class Expert;
24 class SingleDataset;
25 class Weightfile;
26 }
27
28 namespace TrackingUtilities {
31
32 public:
33 Impl(const std::string& identifier, std::vector<Named<Float_t*>> namedVariables);
34 void initialize();
35 void beginRun();
36 std::unique_ptr<MVA::Weightfile> getWeightFile();
37 double predict();
38 std::vector<float> predict(const float* /* test_data */, int /* nFeature */,
39 int /* nRows */);
40 std::vector<std::string> getVariableNames();
41 private:
43 // cppcheck-suppress unusedStructMember ; part of the pimpl state, kept for symmetry with the selected set
44 std::vector<Named<Float_t*> > m_allNamedVariables;
45
47 // cppcheck-suppress unusedStructMember ; part of the pimpl state
48 std::vector<Named<Float_t*> > m_selectedNamedVariables;
49
51 std::unique_ptr<DBObjPtr<DatabaseRepresentationOfWeightfile> > m_weightfileRepresentation;
52
54 std::unique_ptr<MVA::Expert> m_expert;
55
57 std::unique_ptr<MVA::Dataset> m_dataset;
58
60 // cppcheck-suppress unusedStructMember ; part of the pimpl state
62
64 // cppcheck-suppress unusedStructMember ; part of the pimpl state
65 std::string m_identifier;
66 };
67 }
69}
70
72#include <mva/interface/Interface.h>
73
74#include <framework/utilities/FileSystem.h>
75#include <framework/logging/Logger.h>
76
77#include <algorithm>
78
79using namespace Belle2;
80using namespace TrackingUtilities;
81
82MVAExpert::Impl::Impl(const std::string& identifier,
83 std::vector<Named<Float_t*> > namedVariables)
84 : m_allNamedVariables(std::move(namedVariables))
85 , m_identifier(identifier)
86{
87}
88
90{
93 not(m_identifier.ends_with(".root") or m_identifier.ends_with(".xml"))) {
94 using DBWeightFileRepresentation = DBObjPtr<DatabaseRepresentationOfWeightfile>;
95 m_weightfileRepresentation = std::make_unique<DBWeightFileRepresentation>(m_identifier);
96 }
97 if ((not m_weightfileRepresentation) or (not m_weightfileRepresentation->isValid())) {
98 B2FATAL("No weight file could be loaded in tracking/trackingUtilities/mva/MVAExpert.");
99 }
100}
101
103{
104 std::unique_ptr<MVA::Weightfile> weightfile = getWeightFile();
105 // cppcheck-suppress knownConditionTrueFalse ; defensive check on the weightfile representation
106 if (weightfile) {
107 if ((weightfile->getElement<std::string>("method") == "FastBDT" and
108 (weightfile->getElement<int>("FastBDT_version") == 1 or
109 weightfile->getElement<int>("FastBDT_version") == 2)) or
110 (weightfile->getElement<std::string>("method") == "Python")) {
111
112 int nExpectedVars = weightfile->getElement<int>("number_feature_variables");
113
115 for (int iVar = 0; iVar < nExpectedVars; ++iVar) {
116 std::string variableElementName = "variable" + std::to_string(iVar);
117 std::string expectedName = weightfile->getElement<std::string>(variableElementName);
118 auto itNamedVariable = std::find_if(m_allNamedVariables.begin(),
120 [expectedName](const Named<Float_t*>& namedVariable) {
121 return namedVariable.getName() == expectedName;
122 });
123
124 if (itNamedVariable == m_allNamedVariables.end()) {
125 B2ERROR("Variable name " << iVar << " mismatch for FastBDT. " <<
126 "Could not find expected variable '" << expectedName << "'");
127 }
128 m_selectedNamedVariables.push_back(*itNamedVariable);
129 }
130 B2ASSERT("Number of variables mismatch", nExpectedVars == static_cast<int>(m_selectedNamedVariables.size()));
131 } else {
132 B2WARNING("Unpacked new kind of classifier. Consider to extend the feature variable check. Identifier name: " << m_identifier
133 << "; method name: " << weightfile->getElement<std::string>("method"));
135 }
136
137 const std::map<std::string, MVA::AbstractInterface*>& supportedInterfaces =
139 weightfile->getOptions(m_generalOptions);
140 m_expert = supportedInterfaces.at(m_generalOptions.m_method)->getExpert();
141 m_expert->load(*weightfile);
142
143 std::vector<float> dummy;
144 dummy.resize(m_selectedNamedVariables.size(), 0);
145 m_dataset = std::make_unique<MVA::SingleDataset>(m_generalOptions, std::move(dummy), 0);
146 } else {
147 B2ERROR("Could not find weight file for identifier " << m_identifier);
148 }
149}
150
151std::unique_ptr<MVA::Weightfile> MVAExpert::Impl::getWeightFile()
152{
154 std::stringstream ss((*m_weightfileRepresentation)->m_data);
155 return std::make_unique<MVA::Weightfile>(MVA::Weightfile::loadFromStream(ss));
156 } else {
157 std::string weightFilePath = FileSystem::findFile(m_identifier);
158 return std::make_unique<MVA::Weightfile>(MVA::Weightfile::loadFromFile(weightFilePath));
159 }
160}
161
163{
164 if (not m_expert) {
165 B2ERROR("MVA Expert is not loaded! I will return 0");
166 return NAN;
167 }
168
169 // Transfer the extracted values to the data set were the expert can find them
170 for (unsigned int i = 0; i < m_selectedNamedVariables.size(); ++i) {
171 m_dataset->m_input[i] = *m_selectedNamedVariables[i];
172 }
173 return m_expert->apply(*m_dataset)[0];
174}
175
176std::vector<float> MVAExpert::Impl::predict(const float* test_data, int nFeature,
177 int nRows)
178{
179 std::vector<std::vector<float>> spectators;
180 std::vector<std::vector <float> > data;
181 data.resize(nRows);
182 for (int iRow = 0; iRow < nRows; iRow += 1) {
183 data[iRow].resize(nFeature);
184 for (int iFeature = 0; iFeature < nFeature; iFeature += 1) {
185 data[iRow][iFeature] = test_data[nFeature * iRow + iFeature];
186 }
187 }
188
189 MVA::MultiDataset dataSet(m_generalOptions, data, spectators);
190 return m_expert->apply(dataSet);
191}
192
193std::vector<std::string> MVAExpert::Impl::getVariableNames()
194{
195 std::vector<std::string> out(m_selectedNamedVariables.size());
196 for (size_t iName = 0; iName < m_selectedNamedVariables.size(); iName += 1) {
197 out[iName] = m_selectedNamedVariables[iName].getName();
198 }
199 return out;
200}
201
202
204// Silence Doxygen which is complaining that "no matching class member found for"
205// But there should be a better way that I just don't know of / find
207MVAExpert::MVAExpert(const std::string& identifier,
208 std::vector<Named<Float_t*> > namedVariables)
209 : m_impl(std::make_unique<MVAExpert::Impl>(identifier, std::move(namedVariables)))
211{
212}
213
214MVAExpert::~MVAExpert() = default;
215
217{
218 return m_impl->initialize();
219}
220
222{
223 return m_impl->beginRun();
224}
225
227{
228 return m_impl->predict();
229}
230
231std::vector<float> MVAExpert::predict(float* test_data, int nFeature, int nRows)
232{
233 return m_impl->predict(test_data, nFeature, nRows);
234}
235
236std::vector<std::string> MVAExpert::getVariableNames()
237{
238 return m_impl->getVariableNames();
239}
240
Class for accessing objects in the database.
Definition DBObjPtr.h:21
Database representation of a Weightfile object.
static std::string findFile(const std::string &path, bool silent=false)
Search for given file or directory in local or central release directory, and return absolute path if...
static void initSupportedInterfaces()
Static function which initializes all supported interfaces, has to be called once before getSupported...
Definition Interface.cc:46
static const std::map< std::string, AbstractInterface * > & getSupportedInterfaces()
Returns interfaces supported by the MVA Interface.
Definition Interface.h:53
Abstract base class of all Expert Each MVA library has its own implementation of this class,...
Definition Expert.h:31
General options which are shared by all MVA trainings.
Definition Options.h:62
Wraps the data of a multiple event into a Dataset.
Definition Dataset.h:186
Wraps the data of a single event into a Dataset.
Definition Dataset.h:135
The Weightfile class serializes all information about a training into an xml tree.
Definition Weightfile.h:38
static Weightfile loadFromStream(std::istream &stream)
Static function which deserializes a Weightfile from a stream.
static Weightfile loadFromFile(const std::string &filename)
Static function which loads a Weightfile from a file.
Implementation of the class to interact with the MVA package.
Definition MVAExpert.cc:30
void initialize()
Signal the beginning of the event processing.
Definition MVAExpert.cc:89
void beginRun()
Called once before a new run begins.
Definition MVAExpert.cc:102
std::unique_ptr< DBObjPtr< DatabaseRepresentationOfWeightfile > > m_weightfileRepresentation
Database pointer to the Database representation of the weightfile.
Definition MVAExpert.cc:51
std::unique_ptr< MVA::Weightfile > getWeightFile()
Get the weight file.
Definition MVAExpert.cc:151
std::unique_ptr< MVA::Expert > m_expert
Pointer to the current MVA Expert.
Definition MVAExpert.cc:54
std::vector< Named< Float_t * > > m_selectedNamedVariables
References to the selected named values from the source variable set.
Definition MVAExpert.cc:48
Impl(const std::string &identifier, std::vector< Named< Float_t * > > namedVariables)
constructor
Definition MVAExpert.cc:82
std::unique_ptr< MVA::Dataset > m_dataset
Pointer to the current dataset.
Definition MVAExpert.cc:57
std::vector< Named< Float_t * > > m_allNamedVariables
References to the all named values from the source variable set.
Definition MVAExpert.cc:44
MVA::GeneralOptions m_generalOptions
General options.
Definition MVAExpert.cc:61
double predict()
Get the MVA prediction.
Definition MVAExpert.cc:162
std::vector< std::string > getVariableNames()
Get selected variable names.
Definition MVAExpert.cc:193
std::string m_identifier
DB identifier of the expert or file name.
Definition MVAExpert.cc:65
void initialize()
Initialise the mva method.
Definition MVAExpert.cc:216
void beginRun()
Update the mva method to the new run.
Definition MVAExpert.cc:221
std::unique_ptr< Impl > m_impl
Pointer to implementation hiding the details.
Definition MVAExpert.h:59
~MVAExpert()
Destructor must be defined in cpp because of PImpl pointer.
MVAExpert(const std::string &identifier, std::vector< Named< Float_t * > > namedVariables)
Construct the Expert with the specified weight folder and the name of the training that was used in t...
double predict()
Evaluate the MVA method and return the MVAOutput.
Definition MVAExpert.cc:226
std::vector< std::string > getVariableNames()
Get selected variable names.
Definition MVAExpert.cc:236
A mixin class to attach a name to an object.
Definition Named.h:23
Abstract base class for different kinds of events.
STL namespace.