Pandora
Pandora source code navigator
Loading...
Searching...
No Matches
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
14
15#include "Helpers/XmlHelper.h"
16
17#include "Pandora/Algorithm.h"
20#include "Pandora/StatusCodes.h"
21
22#include <chrono>
23#include <ctime>
24#include <fstream>
25
26namespace lar_content
27{
28
32template <typename... Ts>
34{
35public:
36 typedef std::vector<MvaFeatureTool<Ts...> *> FeatureToolVector;
37 typedef std::map<std::string, MvaFeatureTool<Ts...> *> FeatureToolMap;
38
42 MvaFeatureTool() = default;
43
50 virtual void Run(MvaTypes::MvaFeatureVector &featureVector, Ts... args) = 0;
51 virtual void Run(MvaTypes::MvaFeatureMap &featureMap, pandora::StringVector &featureOrder, const std::string &featureToolName, Ts...)
52 {
53 (void)featureMap;
54 (void)featureOrder;
55 (void)featureToolName;
56 return;
57 };
58};
59
60template <typename... Ts>
61using MvaFeatureToolVector = std::vector<MvaFeatureTool<Ts...> *>;
62
63template <typename... Ts>
64using MvaFeatureToolMap = std::map<std::string, MvaFeatureTool<Ts...> *>;
65
66//------------------------------------------------------------------------------------------------------------------------------------------
67
72{
73public:
76 typedef std::map<std::string, double> DoubleMap;
77
79 typedef std::map<std::string, pandora::AlgorithmTool *> AlgorithmToolMap; // idea would be to put this in PandoraInternal.h at some point in PandoraSDK
80
89 template <typename TCONTAINER>
90 static pandora::StatusCode ProduceTrainingExample(const std::string &trainingOutputFile, const bool result, TCONTAINER &&featureContainer);
91
101 template <typename TCONTAINER>
103 const std::string &trainingOutputFile, const bool result, const pandora::StringVector &featureOrder, TCONTAINER &&featureContainer);
104
113 template <typename TCONTAINER>
114 static bool Classify(const MvaInterface &classifier, TCONTAINER &&featureContainer);
115
125 template <typename TCONTAINER>
126 static bool Classify(const MvaInterface &classifier, const pandora::StringVector &featureOrder, TCONTAINER &&featureContainer);
127
136 template <typename TCONTAINER>
137 static double CalculateClassificationScore(const MvaInterface &classifier, TCONTAINER &&featureContainer);
138
147 template <typename TCONTAINER>
148 static double CalculateProbability(const MvaInterface &classifier, TCONTAINER &&featureContainer);
149
159 template <typename TCONTAINER>
160 static double CalculateProbability(const MvaInterface &classifier, const pandora::StringVector &featureOrder, TCONTAINER &&featureContainer);
161
170 template <typename... Ts, typename... TARGS>
171 static MvaFeatureVector CalculateFeatures(const MvaFeatureToolVector<Ts...> &featureToolVector, TARGS &&... args);
172
183 template <typename... Ts, typename... TARGS>
184 static MvaFeatureMap CalculateFeatures(const pandora::StringVector &featureToolOrder, const MvaFeatureToolMap<Ts...> &featureToolMap,
185 pandora::StringVector &featureOrder, TARGS &&... args);
186
195 template <typename T, typename... Ts, typename... TARGS>
196 static MvaFeatureVector CalculateFeaturesOfType(const MvaFeatureToolVector<Ts...> &featureToolVector, TARGS &&... args);
197
206 template <typename... Ts>
208
218 template <typename... Ts>
220 pandora::AlgorithmTool *const pFeatureTool, std::string pFeatureToolName, MvaFeatureToolMap<Ts...> &featureToolMap);
221
231 const std::string &listName, pandora::StringVector &algorithToolNameVector, AlgorithmToolMap &algorithmToolMap);
232
241 template <typename TLIST, typename... TLISTS>
242 static MvaFeatureVector ConcatenateFeatureLists(TLIST &&featureList, TLISTS &&... featureLists);
243
248
249private:
255 static std::string GetTimestampString();
256
266 template <typename TCONTAINER>
267 static pandora::StatusCode WriteFeaturesToFile(std::ofstream &outfile, const std::string &delimiter, TCONTAINER &&featureContainer);
268
278 template <typename TCONTAINER>
279 static pandora::StatusCode WriteFeaturesToFileImpl(std::ofstream &outfile, const std::string &delimiter, TCONTAINER &&featureContainer);
280};
281
282//------------------------------------------------------------------------------------------------------------------------------------------
283
284template <typename TCONTAINER>
285pandora::StatusCode LArMvaHelper::ProduceTrainingExample(const std::string &trainingOutputFile, const bool result, TCONTAINER &&featureContainer)
286{
287 std::ofstream outfile;
288 outfile.open(trainingOutputFile, std::ios_base::app); // always append to the output file
289
290 if (!outfile.is_open())
291 {
292 std::cout << "LArMvaHelper: could not open file for training examples at " << trainingOutputFile << std::endl;
293 return pandora::STATUS_CODE_FAILURE;
294 }
295
296 std::string delimiter(",");
297 outfile << GetTimestampString() << delimiter;
298
299 PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, WriteFeaturesToFile(outfile, delimiter, featureContainer));
300 outfile << static_cast<int>(result) << '\n';
301
302 return pandora::STATUS_CODE_SUCCESS;
303}
304
305//------------------------------------------------------------------------------------------------------------------------------------------
306
307template <typename TCONTAINER>
309 const std::string &trainingOutputFile, const bool result, const pandora::StringVector &featureOrder, TCONTAINER &&featureContainer)
310{
311 // Make a feature vector from the map and calculate the features
312 LArMvaHelper::MvaFeatureVector featureVector;
313
314 for (auto const &pFeatureToolName : featureOrder)
315 {
316 if (featureContainer.find(pFeatureToolName) == featureContainer.end())
317 {
318 std::cout << "LArMvaHelper::ProduceTrainingExample "
319 << "- Error: feature tool " << pFeatureToolName << " not found." << std::endl;
320 throw pandora::StatusCodeException(pandora::STATUS_CODE_NOT_FOUND);
321 }
322 featureVector.push_back(featureContainer.at(pFeatureToolName));
323 }
324
325 return ProduceTrainingExample(trainingOutputFile, result, featureVector);
326}
327
328//------------------------------------------------------------------------------------------------------------------------------------------
329
330template <typename TCONTAINER>
331bool LArMvaHelper::Classify(const MvaInterface &classifier, TCONTAINER &&featureContainer)
332{
333 return classifier.Classify(featureContainer);
334}
335
336//------------------------------------------------------------------------------------------------------------------------------------------
337
338template <typename TCONTAINER>
339bool LArMvaHelper::Classify(const MvaInterface &classifier, const pandora::StringVector &featureOrder, TCONTAINER &&featureContainer)
340{
341 // Make a feature vector from the map and calculate the features
342 LArMvaHelper::MvaFeatureVector featureVector;
343
344 for (auto const &pFeatureToolName : featureOrder)
345 {
346 if (featureContainer.find(pFeatureToolName) == featureContainer.end())
347 {
348 std::cout << "LArMvaHelper::Classify "
349 << "- Error: feature tool " << pFeatureToolName << " not found." << std::endl;
350 throw pandora::StatusCodeException(pandora::STATUS_CODE_NOT_FOUND);
351 }
352 featureVector.push_back(featureContainer.at(pFeatureToolName));
353 }
354
355 return Classify(classifier, featureVector);
356}
357
358//------------------------------------------------------------------------------------------------------------------------------------------
359
360template <typename TCONTAINER>
361double LArMvaHelper::CalculateClassificationScore(const MvaInterface &classifier, TCONTAINER &&featureContainer)
362{
363 return classifier.CalculateClassificationScore(featureContainer);
364}
365
366//------------------------------------------------------------------------------------------------------------------------------------------
367
368template <typename TCONTAINER>
369double LArMvaHelper::CalculateProbability(const MvaInterface &classifier, TCONTAINER &&featureContainer)
370{
371 return classifier.CalculateProbability(featureContainer);
372}
373
374//------------------------------------------------------------------------------------------------------------------------------------------
375
376template <typename TCONTAINER>
377double LArMvaHelper::CalculateProbability(const MvaInterface &classifier, const pandora::StringVector &featureOrder, TCONTAINER &&featureContainer)
378{
379 // Make a feature vector from the map and calculate the features
380 LArMvaHelper::MvaFeatureVector featureVector;
381
382 for (auto const &pFeatureToolName : featureOrder)
383 {
384 if (featureContainer.find(pFeatureToolName) == featureContainer.end())
385 {
386 std::cout << "LArMvaHelper::CalculateProbability "
387 << "- Error: feature tool " << pFeatureToolName << " not found." << std::endl;
388 throw pandora::StatusCodeException(pandora::STATUS_CODE_NOT_FOUND);
389 }
390 featureVector.push_back(featureContainer.at(pFeatureToolName));
391 }
392
393 return CalculateProbability(classifier, featureVector);
394}
395
396//------------------------------------------------------------------------------------------------------------------------------------------
397
398template <typename... Ts, typename... TARGS>
400{
401 LArMvaHelper::MvaFeatureVector featureVector;
402
403 for (MvaFeatureTool<Ts...> *const pFeatureTool : featureToolVector)
404 pFeatureTool->Run(featureVector, std::forward<TARGS>(args)...);
405
406 return featureVector;
407}
408
409//------------------------------------------------------------------------------------------------------------------------------------------
410
411template <typename... Ts, typename... TARGS>
413 const MvaFeatureToolMap<Ts...> &featureToolMap, pandora::StringVector &featureOrder, TARGS &&... args)
414{
416
417 for (auto const &pFeatureToolName : featureToolOrder)
418 {
419 if (featureToolMap.find(pFeatureToolName) == featureToolMap.end())
420 {
421 std::cout << "LArMvaHelper::CalculateFeatures "
422 << "- Error: feature tool " << pFeatureToolName << " not found." << std::endl;
423 throw pandora::StatusCodeException(pandora::STATUS_CODE_NOT_FOUND);
424 }
425 featureToolMap.at(pFeatureToolName)->Run(featureMap, featureOrder, pFeatureToolName, std::forward<TARGS>(args)...);
426 }
427
428 return featureMap;
429}
430
431//------------------------------------------------------------------------------------------------------------------------------------------
432
433template <typename T, typename... Ts, typename... TARGS>
435{
436 using TD = typename std::decay<T>::type;
437 LArMvaHelper::MvaFeatureVector featureVector;
438
439 for (MvaFeatureTool<Ts...> *const pFeatureTool : featureToolVector)
440 {
441 if (TD *const pCastFeatureTool = dynamic_cast<TD *const>(pFeatureTool))
442 pCastFeatureTool->Run(featureVector, std::forward<TARGS>(args)...);
443 }
444
445 return featureVector;
446}
447
448//------------------------------------------------------------------------------------------------------------------------------------------
449
450template <typename... Ts>
452{
453 if (MvaFeatureTool<Ts...> *const pCastFeatureTool = dynamic_cast<MvaFeatureTool<Ts...> *const>(pFeatureTool))
454 {
455 featureToolVector.push_back(pCastFeatureTool);
456 return pandora::STATUS_CODE_SUCCESS;
457 }
458
459 return pandora::STATUS_CODE_FAILURE;
460}
461
462//------------------------------------------------------------------------------------------------------------------------------------------
463
464template <typename... Ts>
466 pandora::AlgorithmTool *const pFeatureTool, std::string pFeatureToolName, MvaFeatureToolMap<Ts...> &featureToolMap)
467{
468 if (MvaFeatureTool<Ts...> *const pCastFeatureTool = dynamic_cast<MvaFeatureTool<Ts...> *const>(pFeatureTool))
469 {
470 featureToolMap[pFeatureToolName] = pCastFeatureTool;
471 return pandora::STATUS_CODE_SUCCESS;
472 }
473
474 return pandora::STATUS_CODE_FAILURE;
475}
476
477//------------------------------------------------------------------------------------------------------------------------------------------
478
480{
481 std::time_t timestampNow = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
482
483 struct tm *pTimeInfo(NULL);
484 char buffer[80];
485
486 pTimeInfo = localtime(&timestampNow);
487 strftime(buffer, 80, "%x_%X", pTimeInfo);
488
489 std::string timeString(buffer);
490
491 if (!timeString.empty() && timeString.back() == '\n') // last char is always a newline
492 timeString.pop_back();
493
494 return timeString;
495}
496
497//------------------------------------------------------------------------------------------------------------------------------------------
498
499template <typename TCONTAINER>
500inline pandora::StatusCode LArMvaHelper::WriteFeaturesToFile(std::ofstream &outfile, const std::string &delimiter, TCONTAINER &&featureContainer)
501{
502 static_assert(std::is_same<typename std::decay<TCONTAINER>::type, LArMvaHelper::MvaFeatureVector>::value,
503 "LArMvaHelper: Could not write training set example because a passed parameter was not a vector of MvaFeatures");
504
505 PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, WriteFeaturesToFileImpl(outfile, delimiter, featureContainer));
506 return pandora::STATUS_CODE_SUCCESS;
507}
508
509//------------------------------------------------------------------------------------------------------------------------------------------
510
511template <typename TCONTAINER>
512pandora::StatusCode LArMvaHelper::WriteFeaturesToFileImpl(std::ofstream &outfile, const std::string &delimiter, TCONTAINER &&featureContainer)
513{
514 for (const MvaFeature &feature : featureContainer)
515 outfile << feature.Get() << delimiter;
516
517 return pandora::STATUS_CODE_SUCCESS;
518}
519
520//------------------------------------------------------------------------------------------------------------------------------------------
521
522template <typename TLIST, typename... TLISTS>
523LArMvaHelper::MvaFeatureVector LArMvaHelper::ConcatenateFeatureLists(TLIST &&featureList, TLISTS &&... featureLists)
524{
525 static_assert(std::is_same<typename std::decay<TLIST>::type, LArMvaHelper::MvaFeatureVector>::value,
526 "LArMvaHelper: Could not concatenate feature lists because one or more lists was not a vector of MvaFeatures");
527
528 LArMvaHelper::MvaFeatureVector featureVector;
529
530 for (const MvaFeature &feature : featureList)
531 featureVector.push_back(feature);
532
533 LArMvaHelper::MvaFeatureVector newFeatureVector = ConcatenateFeatureLists(std::forward<TLISTS>(featureLists)...);
534 featureVector.insert(featureVector.end(), newFeatureVector.begin(), newFeatureVector.end());
535
536 return featureVector;
537}
538
539//------------------------------------------------------------------------------------------------------------------------------------------
540
545
546} // namespace lar_content
547
548#endif // #ifndef LAR_MVA_HELPER_H
Header file for the algorithm class.
Header file for the algorithm tool class.
Header file for the lar multivariate analysis interface class.
Header file for the pandora content api class.
Header file defining relevant internal typedefs, sort and string conversion functions.
Header file defining status codes and relevant preprocessor macros.
#define PANDORA_RETURN_RESULT_IF(StatusCode1, Operator, Command)
Definition StatusCodes.h:19
Header file for the xml helper class.
LArMvaHelper class.
MvaTypes::MvaFeature MvaFeature
static pandora::StatusCode ProcessAlgorithmToolListToMap(const pandora::Algorithm &algorithm, const pandora::TiXmlHandle &xmlHandle, const std::string &listName, pandora::StringVector &algorithToolNameVector, AlgorithmToolMap &algorithmToolMap)
Process a list of algorithms tools in an xml file, using a map. Idea is for this to go to XmlHelper i...
static std::string GetTimestampString()
Get a timestamp string for this point in time.
MvaTypes::MvaFeatureVector MvaFeatureVector
static pandora::StatusCode WriteFeaturesToFileImpl(std::ofstream &outfile, const std::string &delimiter, TCONTAINER &&featureContainer)
Write the features of the given list to file (implementation method)
static pandora::StatusCode WriteFeaturesToFile(std::ofstream &outfile, const std::string &delimiter, TCONTAINER &&featureContainer)
Write the features of the given lists to file.
static double CalculateProbability(const MvaInterface &classifier, TCONTAINER &&featureContainer)
Use the trained mva to calculate a classification probability for an example.
static MvaFeatureVector ConcatenateFeatureLists()
Recursively concatenate vectors of features (terminating method)
static double CalculateClassificationScore(const MvaInterface &classifier, TCONTAINER &&featureContainer)
Use the trained classifer to calculate the classification score of an example (>0 means boolean class...
std::map< std::string, pandora::AlgorithmTool * > AlgorithmToolMap
static bool Classify(const MvaInterface &classifier, TCONTAINER &&featureContainer)
Use the trained classifier to predict the boolean class of an example.
static pandora::StatusCode AddFeatureToolToVector(pandora::AlgorithmTool *const pFeatureTool, MvaFeatureToolVector< Ts... > &featureToolVector)
Add a feature tool to a vector of feature tools.
static MvaFeatureVector CalculateFeaturesOfType(const MvaFeatureToolVector< Ts... > &featureToolVector, TARGS &&... args)
Calculate the features of a given derived feature tool type in a feature tool vector.
static MvaFeatureVector CalculateFeatures(const MvaFeatureToolVector< Ts... > &featureToolVector, TARGS &&... args)
Calculate the features in a given feature tool vector.
static pandora::StatusCode AddFeatureToolToMap(pandora::AlgorithmTool *const pFeatureTool, std::string pFeatureToolName, MvaFeatureToolMap< Ts... > &featureToolMap)
Add a feature tool to a map of feature tools.
static pandora::StatusCode ProduceTrainingExample(const std::string &trainingOutputFile, const bool result, TCONTAINER &&featureContainer)
Produce a training example with the given features and result.
MvaTypes::MvaFeatureMap MvaFeatureMap
std::map< std::string, double > DoubleMap
MvaFeatureTool class template.
std::vector< MvaFeatureTool< Ts... > * > FeatureToolVector
virtual void Run(MvaTypes::MvaFeatureMap &featureMap, pandora::StringVector &featureOrder, const std::string &featureToolName, Ts...)
virtual void Run(MvaTypes::MvaFeatureVector &featureVector, Ts... args)=0
Run the algorithm tool.
MvaFeatureTool()=default
Default constructor.
std::map< std::string, MvaFeatureTool< Ts... > * > FeatureToolMap
MvaInterface class.
virtual double CalculateClassificationScore(const MvaTypes::MvaFeatureVector &features) const =0
Calculate the classification score for a set of input features, based on the trained model.
virtual bool Classify(const MvaTypes::MvaFeatureVector &features) const =0
Classify the set of input features based on the trained model.
virtual double CalculateProbability(const MvaTypes::MvaFeatureVector &features) const =0
Calculate the classification probability for a set of input features, based on the trained model.
InitializedDouble class used to define mva features.
Algorithm class. Algorithm addresses are held only by the algorithm manager. They have a fully define...
Definition Algorithm.h:21
AlgorithmTool class. Algorithm tools will tend to be tailored for specific parent algorithms,...
StatusCodeException class.
std::map< std::string, MvaFeatureTool< Ts... > * > MvaFeatureToolMap
std::vector< MvaFeatureTool< Ts... > * > MvaFeatureToolVector
std::vector< MvaFeature > MvaFeatureVector
std::map< std::string, MvaFeature > MvaFeatureMap
std::vector< std::string > StringVector
StatusCode
The StatusCode enum.