LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
LArMvaHelper.h
Go to the documentation of this file.
1 
8 #ifndef LAR_MVA_HELPER_H
9 #define LAR_MVA_HELPER_H 1
10 
12 
13 #include "Pandora/AlgorithmTool.h"
14 #include "Pandora/StatusCodes.h"
15 
16 #include <fstream>
17 #include <chrono>
18 #include <ctime>
19 
20 namespace lar_content
21 {
22 
26 template <typename ...Ts>
27 class MvaFeatureTool : public pandora::AlgorithmTool
28 {
29 public:
31 
35  MvaFeatureTool() = default;
36 
43  virtual void Run(MvaTypes::MvaFeatureVector &featureVector, Ts... args) = 0;
44 };
45 
46 template <typename ...Ts>
48 
49 //------------------------------------------------------------------------------------------------------------------------------------------
50 
55 {
56 public:
59 
68  template <typename ...TLISTS>
69  static pandora::StatusCode ProduceTrainingExample(const std::string &trainingOutputFile, const bool result, TLISTS &&... featureLists);
70 
79  template <typename ...TLISTS>
80  static bool Classify(const MvaInterface &classifier, TLISTS &&... featureLists);
81 
90  template <typename ...TLISTS>
91  static double CalculateClassificationScore(const MvaInterface &classifier, TLISTS &&... featureLists);
92 
101  template <typename ...TLISTS>
102  static double CalculateProbability(const MvaInterface &classifier, TLISTS &&... featureLists);
103 
112  template <typename ...Ts, typename ...TARGS>
113  static MvaFeatureVector CalculateFeatures(const MvaFeatureToolVector<Ts...> &featureToolVector, TARGS &&... args);
114 
123  template <typename T, typename ...Ts, typename ...TARGS>
124  static MvaFeatureVector CalculateFeaturesOfType(const MvaFeatureToolVector<Ts...> &featureToolVector, TARGS &&... args);
125 
134  template <typename ...Ts>
135  static pandora::StatusCode AddFeatureToolToVector(pandora::AlgorithmTool *const pFeatureTool, MvaFeatureToolVector<Ts...> &featureToolVector);
136 
137 private:
143  static std::string GetTimestampString();
144 
155  template <typename TLIST, typename ...TLISTS>
156  static pandora::StatusCode WriteFeaturesToFile(std::ofstream &outfile, const std::string &delimiter, TLIST &&featureList, TLISTS &&... featureLists);
157 
163  static pandora::StatusCode WriteFeaturesToFile(std::ofstream &, const std::string &);
164 
174  template <typename TLIST>
175  static pandora::StatusCode WriteFeaturesToFileImpl(std::ofstream &outfile, const std::string &delimiter, TLIST &&featureList);
176 
185  template <typename TLIST, typename ...TLISTS>
186  static MvaFeatureVector ConcatenateFeatureLists(TLIST &&featureList, TLISTS &&... featureLists);
187 
191  static MvaFeatureVector ConcatenateFeatureLists();
192 };
193 
194 //------------------------------------------------------------------------------------------------------------------------------------------
195 
196 template <typename ...TLISTS>
197 pandora::StatusCode LArMvaHelper::ProduceTrainingExample(const std::string &trainingOutputFile, const bool result, TLISTS &&... featureLists)
198 {
199  std::ofstream outfile;
200  outfile.open(trainingOutputFile, std::ios_base::app); // always append to the output file
201 
202  if (!outfile.is_open())
203  {
204  std::cout << "LArMvaHelper: could not open file for training examples at " << trainingOutputFile << std::endl;
205  return pandora::STATUS_CODE_FAILURE;
206  }
207 
208  std::string delimiter(",");
209  outfile << GetTimestampString() << delimiter;
210 
211  PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, WriteFeaturesToFile(outfile, delimiter, featureLists...));
212  outfile << static_cast<int>(result) << '\n';
213 
214  return pandora::STATUS_CODE_SUCCESS;
215 }
216 
217 //------------------------------------------------------------------------------------------------------------------------------------------
218 
219 template <typename ...TLISTS>
220 bool LArMvaHelper::Classify(const MvaInterface &classifier, TLISTS &&... featureLists)
221 {
222  return classifier.Classify(ConcatenateFeatureLists(std::forward<TLISTS>(featureLists)...));
223 }
224 
225 //------------------------------------------------------------------------------------------------------------------------------------------
226 
227 template <typename ...TLISTS>
228 double LArMvaHelper::CalculateClassificationScore(const MvaInterface &classifier, TLISTS &&... featureLists)
229 {
230  return classifier.CalculateClassificationScore(ConcatenateFeatureLists(std::forward<TLISTS>(featureLists)...));
231 }
232 
233 //------------------------------------------------------------------------------------------------------------------------------------------
234 
235 template <typename ...TLISTS>
236 double LArMvaHelper::CalculateProbability(const MvaInterface &classifier, TLISTS &&... featureLists)
237 {
238  return classifier.CalculateProbability(ConcatenateFeatureLists(std::forward<TLISTS>(featureLists)...));
239 }
240 
241 //------------------------------------------------------------------------------------------------------------------------------------------
242 
243 template <typename ...Ts, typename ...TARGS>
245 {
246  LArMvaHelper::MvaFeatureVector featureVector;
247 
248  for (MvaFeatureTool<Ts...> *const pFeatureTool : featureToolVector)
249  pFeatureTool->Run(featureVector, std::forward<TARGS>(args)...);
250 
251  return featureVector;
252 }
253 
254 //------------------------------------------------------------------------------------------------------------------------------------------
255 
256 template <typename T, typename ...Ts, typename ...TARGS>
258 {
259  using TD = typename std::decay<T>::type;
260  LArMvaHelper::MvaFeatureVector featureVector;
261 
262  for (MvaFeatureTool<Ts...> *const pFeatureTool : featureToolVector)
263  {
264  if (TD *const pCastFeatureTool = dynamic_cast<TD *const>(pFeatureTool))
265  pCastFeatureTool->Run(featureVector, std::forward<TARGS>(args)...);
266  }
267 
268  return featureVector;
269 }
270 
271 //------------------------------------------------------------------------------------------------------------------------------------------
272 
273 template <typename ...Ts>
274 pandora::StatusCode LArMvaHelper::AddFeatureToolToVector(pandora::AlgorithmTool *const pFeatureTool, MvaFeatureToolVector<Ts...> &featureToolVector)
275 {
276  if (MvaFeatureTool<Ts...> *const pCastFeatureTool = dynamic_cast<MvaFeatureTool<Ts...> *const>(pFeatureTool))
277  {
278  featureToolVector.push_back(pCastFeatureTool);
279  return pandora::STATUS_CODE_SUCCESS;
280  }
281 
282  return pandora::STATUS_CODE_FAILURE;
283 }
284 
285 //------------------------------------------------------------------------------------------------------------------------------------------
286 
288 {
289  std::time_t timestampNow = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
290 
291  struct tm *pTimeInfo(NULL);
292  char buffer[80];
293 
294  pTimeInfo = localtime(&timestampNow);
295  strftime(buffer, 80, "%x_%X", pTimeInfo);
296 
297  std::string timeString(buffer);
298 
299  if (!timeString.empty() && timeString.back() == '\n') // last char is always a newline
300  timeString.pop_back();
301 
302  return timeString;
303 }
304 
305 //------------------------------------------------------------------------------------------------------------------------------------------
306 
307 template <typename TLIST, typename ...TLISTS>
308 inline pandora::StatusCode LArMvaHelper::WriteFeaturesToFile(std::ofstream &outfile, const std::string &delimiter, TLIST &&featureList, TLISTS &&... featureLists)
309 {
310  static_assert(std::is_same<typename std::decay<TLIST>::type, LArMvaHelper::MvaFeatureVector>::value,
311  "LArMvaHelper: Could not write training set example because a passed parameter was not a vector of MvaFeatures");
312 
313  PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, WriteFeaturesToFileImpl(outfile, delimiter, featureList));
314  return WriteFeaturesToFile(outfile, delimiter, featureLists...);
315 }
316 
317 //------------------------------------------------------------------------------------------------------------------------------------------
318 
319 inline pandora::StatusCode LArMvaHelper::WriteFeaturesToFile(std::ofstream &, const std::string &)
320 {
321  return pandora::STATUS_CODE_SUCCESS;
322 }
323 
324 //------------------------------------------------------------------------------------------------------------------------------------------
325 
326 template <typename TLIST>
327 pandora::StatusCode LArMvaHelper::WriteFeaturesToFileImpl(std::ofstream &outfile, const std::string &delimiter, TLIST &&featureList)
328 {
329  for (const MvaFeature feature : featureList)
330  outfile << feature.Get() << delimiter;
331 
332  return pandora::STATUS_CODE_SUCCESS;
333 }
334 
335 //------------------------------------------------------------------------------------------------------------------------------------------
336 
337 template <typename TLIST, typename ...TLISTS>
338 LArMvaHelper::MvaFeatureVector LArMvaHelper::ConcatenateFeatureLists(TLIST &&featureList, TLISTS &&... featureLists)
339 {
340  static_assert(std::is_same<typename std::decay<TLIST>::type, LArMvaHelper::MvaFeatureVector>::value,
341  "LArMvaHelper: Could not concatenate feature lists because one or more lists was not a vector of MvaFeatures");
342 
343  LArMvaHelper::MvaFeatureVector featureVector;
344 
345  for (const MvaFeature feature : featureList)
346  featureVector.push_back(feature);
347 
348  LArMvaHelper::MvaFeatureVector newFeatureVector = ConcatenateFeatureLists(std::forward<TLISTS>(featureLists)...);
349  featureVector.insert(featureVector.end(), newFeatureVector.begin(), newFeatureVector.end());
350 
351  return featureVector;
352 }
353 
354 //------------------------------------------------------------------------------------------------------------------------------------------
355 
357 {
359 }
360 
361 } // namespace lar_content
362 
363 #endif // #ifndef LAR_MVA_HELPER_H
static double CalculateProbability(const MvaInterface &classifier, TLISTS &&...featureLists)
Use the trained mva to calculate a classification probability for an example.
Definition: LArMvaHelper.h:236
static pandora::StatusCode WriteFeaturesToFileImpl(std::ofstream &outfile, const std::string &delimiter, TLIST &&featureList)
Write the features of the given list to file (implementation method)
Definition: LArMvaHelper.h:327
MvaTypes::MvaFeatureVector MvaFeatureVector
Definition: LArMvaHelper.h:58
MvaFeatureTool()=default
Default constructor.
virtual void Run(MvaTypes::MvaFeatureVector &featureVector, Ts...args)=0
Run the algorithm tool.
static std::string GetTimestampString()
Get a timestamp string for this point in time.
Definition: LArMvaHelper.h:287
static pandora::StatusCode WriteFeaturesToFile(std::ofstream &outfile, const std::string &delimiter, TLIST &&featureList, TLISTS &&...featureLists)
Recursively write the features of the given lists to file.
Definition: LArMvaHelper.h:308
MvaInterface class.
static bool Classify(const MvaInterface &classifier, TLISTS &&...featureLists)
Use the trained classifier to predict the boolean class of an example.
Definition: LArMvaHelper.h:220
std::vector< MvaFeatureTool< Ts... > * > MvaFeatureToolVector
Definition: LArMvaHelper.h:47
MvaTypes::MvaFeature MvaFeature
Definition: LArMvaHelper.h:57
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
static double CalculateClassificationScore(const MvaInterface &classifier, TLISTS &&...featureLists)
Use the trained classifer to calculate the classification score of an example (>0 means boolean class...
Definition: LArMvaHelper.h:228
static pandora::StatusCode ProduceTrainingExample(const std::string &trainingOutputFile, const bool result, TLISTS &&...featureLists)
Produce a training example with the given features and result.
Definition: LArMvaHelper.h:197
virtual bool Classify(const MvaTypes::MvaFeatureVector &features) const =0
Classify the set of input features based on the trained model.
static MvaFeatureVector CalculateFeaturesOfType(const MvaFeatureToolVector< Ts... > &featureToolVector, TARGS &&...args)
Calculate the features of a given derived feature tool type in a feature tool vector.
Definition: LArMvaHelper.h:257
InitializedDouble class used to define mva features.
static pandora::StatusCode AddFeatureToolToVector(pandora::AlgorithmTool *const pFeatureTool, MvaFeatureToolVector< Ts... > &featureToolVector)
Add a feature tool to a vector of feature tools.
Definition: LArMvaHelper.h:274
LArMvaHelper class.
Definition: LArMvaHelper.h:54
virtual double CalculateProbability(const MvaTypes::MvaFeatureVector &features) const =0
Calculate the classification probability for a set of input features, based on the trained model...
std::string value(boost::any const &)
std::vector< MvaFeatureTool< Ts... > * > FeatureToolVector
Definition: LArMvaHelper.h:30
virtual double CalculateClassificationScore(const MvaTypes::MvaFeatureVector &features) const =0
Calculate the classification score for a set of input features, based on the trained model...
static MvaFeatureVector CalculateFeatures(const MvaFeatureToolVector< Ts... > &featureToolVector, TARGS &&...args)
Calculate the features in a given feature tool vector.
Definition: LArMvaHelper.h:244
static MvaFeatureVector ConcatenateFeatureLists()
Recursively concatenate vectors of features (terminating method)
Definition: LArMvaHelper.h:356
MvaFeatureTool class template.
Definition: LArMvaHelper.h:27
std::vector< MvaFeature > MvaFeatureVector
Header file for the lar multivariate analysis interface class.