// Class: ReadFisher
// Automatically generated by MethodBase::MakeClass
//

/* configuration options =====================================================

#GEN -*-*-*-*-*-*-*-*-*-*-*- general info -*-*-*-*-*-*-*-*-*-*-*-

Method         : Fisher::Fisher
TMVA Release   : 4.2.1         [262657]
ROOT Release   : 6.22/06       [398854]
Creator        : glencowan
Date           : Wed Nov  3 00:36:24 2021
Host           : Darwin bigsurx.internal.macports.net 20.1.0 Darwin Kernel Version 20.1.0: Sat Oct 31 00:07:11 PDT 2020; root:xnu-7195.50.7~2/RELEASE_X86_64 x86_64
Dir            : /Users/glencowan/cowan/teach/ph4515/21/problems/ps5/tmva/train
Training events: 2000
Analysis type  : [Classification]


#OPT -*-*-*-*-*-*-*-*-*-*-*-*- options -*-*-*-*-*-*-*-*-*-*-*-*-

# Set by User:
V: "False" [Verbose output (short form of "VerbosityLevel" below - overrides the latter one)]
H: "True" [Print method-specific help message]
Method: "Fisher" [Discrimination method]
# Default:
VerbosityLevel: "Default" [Verbosity level]
VarTransform: "None" [List of variable transformations performed before training, e.g., "D_Background,P_Signal,G,N_AllClasses" for: "Decorrelation, PCA-transformation, Gaussianisation, Normalisation, each for the given class of events ('AllClasses' denotes all events of all classes, if no class indication is given, 'All' is assumed)"]
CreateMVAPdfs: "False" [Create PDFs for classifier outputs (signal and background)]
IgnoreNegWeightsInTraining: "False" [Events with negative weights are ignored in the training (but are included for testing and performance evaluation)]
##


#VAR -*-*-*-*-*-*-*-*-*-*-*-* variables *-*-*-*-*-*-*-*-*-*-*-*-

NVar 3
x                             x                             x                             x                                                               'F'    [-3.60392403603,3.5663151741]
y                             y                             y                             y                                                               'F'    [-2.58809733391,4.20677995682]
z                             z                             z                             z                                                               'F'    [0.000381360063329,0.998853266239]
NSpec 0


============================================================================ */

#include <array>
#include <vector>
#include <cmath>
#include <string>
#include <iostream>

#ifndef IClassifierReader__def
#define IClassifierReader__def

class IClassifierReader {

 public:

   // constructor
   IClassifierReader() : fStatusIsClean( true ) {}
   virtual ~IClassifierReader() {}

   // return classifier response
   virtual double GetMvaValue( const std::vector<double>& inputValues ) const = 0;

   // returns classifier status
   bool IsStatusClean() const { return fStatusIsClean; }

 protected:

   bool fStatusIsClean;
};

#endif

class ReadFisher : public IClassifierReader {

 public:

   // constructor
   ReadFisher( std::vector<std::string>& theInputVars )
      : IClassifierReader(),
        fClassName( "ReadFisher" ),
        fNvars( 3 )
   {
      // the training input variables
      const char* inputVars[] = { "x", "y", "z" };

      // sanity checks
      if (theInputVars.size() <= 0) {
         std::cout << "Problem in class \"" << fClassName << "\": empty input vector" << std::endl;
         fStatusIsClean = false;
      }

      if (theInputVars.size() != fNvars) {
         std::cout << "Problem in class \"" << fClassName << "\": mismatch in number of input values: "
                   << theInputVars.size() << " != " << fNvars << std::endl;
         fStatusIsClean = false;
      }

      // validate input variables
      for (size_t ivar = 0; ivar < theInputVars.size(); ivar++) {
         if (theInputVars[ivar] != inputVars[ivar]) {
            std::cout << "Problem in class \"" << fClassName << "\": mismatch in input variable names" << std::endl
                      << " for variable [" << ivar << "]: " << theInputVars[ivar].c_str() << " != " << inputVars[ivar] << std::endl;
            fStatusIsClean = false;
         }
      }

      // initialize min and max vectors (for normalisation)
      fVmin[0] = 0;
      fVmax[0] = 0;
      fVmin[1] = 0;
      fVmax[1] = 0;
      fVmin[2] = 0;
      fVmax[2] = 0;

      // initialize input variable types
      fType[0] = 'F';
      fType[1] = 'F';
      fType[2] = 'F';

      // initialize constants
      Initialize();

   }

   // destructor
   virtual ~ReadFisher() {
      Clear(); // method-specific
   }

   // the classifier response
   // "inputValues" is a vector of input values in the same order as the
   // variables given to the constructor
   double GetMvaValue( const std::vector<double>& inputValues ) const override;

 private:

   // method-specific destructor
   void Clear();

   // common member variables
   const char* fClassName;

   const size_t fNvars;
   size_t GetNvar()           const { return fNvars; }
   char   GetType( int ivar ) const { return fType[ivar]; }

   // normalisation of input variables
   double fVmin[3];
   double fVmax[3];
   double NormVariable( double x, double xmin, double xmax ) const {
      // normalise to output range: [-1, 1]
      return 2*(x - xmin)/(xmax - xmin) - 1.0;
   }

   // type of input variable: 'F' or 'I'
   char   fType[3];

   // initialize internal variables
   void Initialize();
   double GetMvaValue__( const std::vector<double>& inputValues ) const;

   // private members (method specific)
   double              fFisher0;
   std::vector<double> fFisherCoefficients;
};

inline void ReadFisher::Initialize() 
{
   fFisher0 = 0.960077401312;
   fFisherCoefficients.push_back( -0.0237260150151 );
   fFisherCoefficients.push_back( -0.444975802686 );
   fFisherCoefficients.push_back( -1.06821375856 );

   // sanity check
   if (fFisherCoefficients.size() != fNvars) {
      std::cout << "Problem in class \"" << fClassName << "\"::Initialize: mismatch in number of input values"
                << fFisherCoefficients.size() << " != " << fNvars << std::endl;
      fStatusIsClean = false;
   }         
}

inline double ReadFisher::GetMvaValue__( const std::vector<double>& inputValues ) const
{
   double retval = fFisher0;
   for (size_t ivar = 0; ivar < fNvars; ivar++) {
      retval += fFisherCoefficients[ivar]*inputValues[ivar];
   }

   return retval;
}

// Clean up
inline void ReadFisher::Clear() 
{
   // clear coefficients
   fFisherCoefficients.clear(); 
}
inline double ReadFisher::GetMvaValue( const std::vector<double>& inputValues ) const
{
   // classifier response value
   double retval = 0;

   // classifier response, sanity check first
   if (!IsStatusClean()) {
      std::cout << "Problem in class \"" << fClassName << "\": cannot return classifier response"
                << " because status is dirty" << std::endl;
   }
   else {
         retval = GetMvaValue__( inputValues );
   }

   return retval;
}
