// @(#)root/tmva $Id$
// Author: Andreas Hoecker, Joerg Stelzer, Helge Voss, Eckhard v. Toerne

/**********************************************************************************
 * Project: TMVA - a Root-integrated toolkit for multivariate data analysis       *
 * Package: TMVA                                                                  *
 * Class  : VariableGaussTransform                                                *
 * Web    : http://tmva.sourceforge.net                                           *
 *                                                                                *
 * Description:                                                                   *
 *      Implementation (see header for description)                               *
 *                                                                                *
 * Authors (alphabetical):                                                        *
 *      Andreas Hoecker <Andreas.Hocker@cern.ch> - CERN, Switzerland              *
 *      Peter Speckmayer <Peter.Speckmayer@cern.ch> - CERN, Switzerland           *
 *      Joerg Stelzer   <Joerg.Stelzer@cern.ch>  - CERN, Switzerland              *
 *      Eckhard v. Toerne     <evt@uni-bonn.de>  - Uni Bonn, Germany              *
 *      Helge Voss      <Helge.Voss@cern.ch>     - MPI-K Heidelberg, Germany      *
 *                                                                                *
 * Copyright (c) 2005-2011:                                                       *
 *      CERN, Switzerland                                                         *
 *      MPI-K Heidelberg, Germany                                                 *
 *      U. of Bonn, Germany                                                       *
 *                                                                                *
 * Redistribution and use in source and binary forms, with or without             *
 * modification, are permitted according to the terms listed in LICENSE           *
 * (http://tmva.sourceforge.net/LICENSE)                                          *
 **********************************************************************************/

///////////////////////////////////////////////////////////////////////////
//                                                                       //
// Gaussian Transformation of input variables.                           //
//                                                                       //
///////////////////////////////////////////////////////////////////////////

#include <iostream>
#include <iomanip>
#include <list>
#include <limits>
#include <exception>
#include <stdexcept>

#include "TVectorF.h"
#include "TVectorD.h"
#include "TMath.h"
#include "TCanvas.h"

#include "TMVA/VariableGaussTransform.h"
#ifndef ROOT_TMVA_MsgLogger
#include "TMVA/MsgLogger.h"
#endif
#ifndef ROOT_TMVA_Tools
#include "TMVA/Tools.h"
#endif
#ifndef ROOT_TMVA_Version
#include "TMVA/Version.h"
#endif

ClassImp(TMVA::VariableGaussTransform)

//_______________________________________________________________________
TMVA::VariableGaussTransform::VariableGaussTransform( DataSetInfo& dsi, TString strcor )
   : VariableTransformBase( dsi, Types::kGauss, "Gauss" ),
     fFlatNotGauss(kFALSE),
     fPdfMinSmooth(0),
     fPdfMaxSmooth(0),
     fElementsperbin(0)
{ 
   // constructor
   // can only be applied one after the other when they are created. But in order to
   // determine the Gauss transformation
  if (strcor=="Uniform") {fFlatNotGauss = kTRUE;
    SetName("Uniform");
  }
}

//_______________________________________________________________________
TMVA::VariableGaussTransform::~VariableGaussTransform( void )
{
   // destructor
   CleanUpCumulativeArrays();
}

//_______________________________________________________________________
void TMVA::VariableGaussTransform::Initialize()
{

}

//_______________________________________________________________________
Bool_t TMVA::VariableGaussTransform::PrepareTransformation (const std::vector<Event*>& events)
{
   // calculate the cumulative distributions
   Initialize();

   if (!IsEnabled() || IsCreated()) return kTRUE;

   Log() << kINFO << "Preparing the Gaussian transformation..." << Endl;

   UInt_t inputSize = fGet.size();
   SetNVariables(inputSize);

   if (inputSize > 200) { 
      Log() << kWARNING << "----------------------------------------------------------------------------" 
              << Endl;
      Log() << kWARNING 
              << ": More than 200 variables, I hope you have enough memory!!!!" << Endl;
      Log() << kWARNING << "----------------------------------------------------------------------------" 
              << Endl;
      //      return kFALSE;
   }   

   GetCumulativeDist( events );
   
   SetCreated( kTRUE );

   return kTRUE;
}

//_______________________________________________________________________
const TMVA::Event* TMVA::VariableGaussTransform::Transform(const Event* const ev, Int_t cls ) const
{
   // apply the Gauss transformation

   if (!IsCreated()) Log() << kFATAL << "Transformation not yet created" << Endl;
   //EVT this is a workaround to address the reader problem with transforma and EvaluateMVA(std::vector<float/double> ,...) 
   //EVT if (cls <0 || cls > GetNClasses() ) {
   //EVT   cls = GetNClasses();
   //EVT   if (GetNClasses() == 1 ) cls = (fCumulativePDF[0].size()==1?0:2);
   //EVT}
   if (cls <0 || cls >=  (int) fCumulativePDF[0].size()) cls = fCumulativePDF[0].size()-1;
   //EVT workaround end

  // get the variable vector of the current event
   UInt_t inputSize = fGet.size();

   std::vector<Float_t> input(0);
   std::vector<Float_t> output(0);

   std::vector<Char_t> mask; // entries with kTRUE must not be transformed
   GetInput( ev, input, mask );

   std::vector<Char_t>::iterator itMask = mask.begin();
   
//   TVectorD vec( inputSize );
//   for (UInt_t ivar=0; ivar<inputSize; ivar++) vec(ivar) = input.at(ivar);
   Double_t cumulant;
   //transformation   
   for (UInt_t ivar=0; ivar<inputSize; ivar++) {

      if ( (*itMask) ){
	 ++itMask;
	 continue;
      }

      if (0 != fCumulativePDF[ivar][cls]) { 
         // first make it flat
         if(fTMVAVersion>TMVA_VERSION(3,9,7))
            cumulant = (fCumulativePDF[ivar][cls])->GetVal(input.at(ivar)); 
         else
            cumulant = OldCumulant(input.at(ivar), fCumulativePDF[ivar][cls]->GetOriginalHist() );
         cumulant = TMath::Min(cumulant,1.-10e-10);
         cumulant = TMath::Max(cumulant,0.+10e-10);

         if (fFlatNotGauss)
            output.push_back( cumulant ); 
         else {
            // sanity correction for out-of-range values
            Double_t maxErfInvArgRange = 0.99999999;
            Double_t arg = 2.0*cumulant - 1.0;
            arg = TMath::Min(+maxErfInvArgRange,arg);
            arg = TMath::Max(-maxErfInvArgRange,arg);
            
            output.push_back( 1.414213562*TMath::ErfInverse(arg) );
         }
      }
   }
   
   if (fTransformedEvent==0 || fTransformedEvent->GetNVariables()!=ev->GetNVariables()) {
      if (fTransformedEvent!=0) { delete fTransformedEvent; fTransformedEvent = 0; }
      fTransformedEvent = new Event();
   }

   SetOutput( fTransformedEvent, output, mask, ev );

   return fTransformedEvent;
}

//_______________________________________________________________________
const TMVA::Event* TMVA::VariableGaussTransform::InverseTransform(const  Event* const ev, Int_t cls ) const
{
   // apply the inverse Gauss or inverse uniform transformation

   if (!IsCreated()) Log() << kFATAL << "Transformation not yet created" << Endl;
   //EVT this is a workaround to address the reader problem with transforma and EvaluateMVA(std::vector<float/double> ,...) 
   //EVT if (cls <0 || cls > GetNClasses() ) {
   //EVT   cls = GetNClasses();
   //EVT   if (GetNClasses() == 1 ) cls = (fCumulativePDF[0].size()==1?0:2);
   //EVT}
   if (cls <0 || cls >=  (int) fCumulativePDF[0].size()) cls = fCumulativePDF[0].size()-1;
   //EVT workaround end

  // get the variable vector of the current event
   UInt_t inputSize = fGet.size();

   std::vector<Float_t> input(0);
   std::vector<Float_t> output(0);

   std::vector<Char_t> mask; // entries with kTRUE must not be transformed
   GetInput( ev, input, mask, kTRUE );

   std::vector<Char_t>::iterator itMask = mask.begin();
   
//   TVectorD vec( inputSize );
//   for (UInt_t ivar=0; ivar<inputSize; ivar++) vec(ivar) = input.at(ivar);
   Double_t invCumulant;
   //transformation   
   for (UInt_t ivar=0; ivar<inputSize; ivar++) {

      if ( (*itMask) ){
	 ++itMask;
	 continue;
      }

      if (0 != fCumulativePDF[ivar][cls]) { 
	 invCumulant = input.at(ivar);

         // first de-gauss ist if gaussianized
         if (!fFlatNotGauss)
            invCumulant = (TMath::Erf(invCumulant/1.414213562)+1)/2.f;

	 // then de-uniform the values
	 if(fTMVAVersion>TMVA_VERSION(4,0,0))
	    invCumulant = (fCumulativePDF[ivar][cls])->GetValInverse(invCumulant,kTRUE); 
	 else
	    Log() << kFATAL << "Inverse Uniform/Gauss transformation not implemented for TMVA versions before 4.1.0" << Endl;

	 output.push_back(invCumulant);
      }
   }
   
   if (fBackTransformedEvent==0) fBackTransformedEvent = new Event( *ev );

   SetOutput( fBackTransformedEvent, output, mask, ev, kTRUE );

   return fBackTransformedEvent;
}

//_______________________________________________________________________
void TMVA::VariableGaussTransform::GetCumulativeDist( const std::vector< Event*>& events )
{
   // fill the cumulative distributions

   const UInt_t inputSize = fGet.size();
//   const UInt_t nCls = GetNClasses();

//   const UInt_t nvar = GetNVariables();
   UInt_t nevt = events.size();
   
   const UInt_t nClasses = GetNClasses();
   UInt_t numDist  = nClasses+1; // calculate cumulative distributions for all "event" classes seperately + one where all classes are treated (added) together
      
   if (GetNClasses() == 1 ) numDist = nClasses; // for regression, if there is only one class, there is no "sum" of classes, hence 
 
   UInt_t **nbins = new UInt_t*[numDist];

   std::list< TMVA::TMVAGaussPair >  **listsForBinning = new std::list<TMVA::TMVAGaussPair>* [numDist];
   std::vector< Float_t >   **vsForBinning = new std::vector<Float_t>* [numDist];
   for (UInt_t i=0; i < numDist; i++) {
      listsForBinning[i] = new std::list<TMVA::TMVAGaussPair> [inputSize];
      vsForBinning[i]    = new std::vector<Float_t> [inputSize];
      nbins[i] = new UInt_t[inputSize];  // nbins[0] = number of bins for signal distributions. It depends on the number of entries, thus it's the same for all the input variables, but it isn't necessary for some "weird" reason.
   }

   std::vector<Float_t> input;
   std::vector<Char_t> mask; // entries with kTRUE must not be transformed

   // perform event loop
   Float_t *sumOfWeights = new Float_t[numDist]; 
   Float_t *minWeight = new Float_t[numDist]; 
   Float_t *maxWeight = new Float_t[numDist]; 
   for (UInt_t i=0; i<numDist; i++) {
      sumOfWeights[i]=0;
      minWeight[i]=10E10; // TODO: change this to std::max ?
      maxWeight[i]=0; // QUESTION: wouldn't there be negative events possible?
   }
   for (UInt_t ievt=0; ievt < nevt; ievt++) {
      const Event* ev= events[ievt];
      Int_t cls = ev->GetClass();
      Float_t eventWeight = ev->GetWeight();
      sumOfWeights[cls] += eventWeight;
      if (minWeight[cls] > eventWeight) minWeight[cls]=eventWeight;
      if (maxWeight[cls] < eventWeight) maxWeight[cls]=eventWeight;
      if (numDist>1) sumOfWeights[numDist-1] += eventWeight;

      Bool_t hasMaskedEntries = GetInput( ev, input, mask );
      if( hasMaskedEntries ){
	 Log() << kWARNING << "Incomplete event" << Endl;
	 ev->Print(Log());
	 Log() << kFATAL << "Targets or variables masked by transformation. Apparently (a) value(s) is/are missing in this event." << Endl;
      }
	 

      Int_t ivar = 0;
      for( std::vector<Float_t>::iterator itInput = input.begin(), itInputEnd = input.end(); itInput != itInputEnd; ++itInput ) {
	 Float_t value = (*itInput);
         listsForBinning[cls][ivar].push_back(TMVA::TMVAGaussPair(value,eventWeight));  
         if (numDist>1)listsForBinning[numDist-1][ivar].push_back(TMVA::TMVAGaussPair(value,eventWeight));  
	 ++ivar;
      }  
   }
   if (numDist > 1) {
      for (UInt_t icl=0; icl<numDist-1; icl++){
         minWeight[numDist-1] = TMath::Min(minWeight[icl],minWeight[numDist-1]);
         maxWeight[numDist-1] = TMath::Max(maxWeight[icl],maxWeight[numDist-1]);
      }
   }

   // Sorting the lists, getting nbins ...
   const UInt_t nevmin=10;  // minimum number of events per bin (to make sure we get reasonable distributions)
   const UInt_t nbinsmax=2000; // maximum number of bins

   for (UInt_t icl=0; icl< numDist; icl++){
      for (UInt_t ivar=0; ivar<inputSize; ivar++) {
         listsForBinning[icl][ivar].sort();  
         std::list< TMVA::TMVAGaussPair >::iterator it;
         Float_t sumPerBin = sumOfWeights[icl]/nbinsmax;
         sumPerBin=TMath::Max(minWeight[icl]*nevmin,sumPerBin);
         Float_t sum=0;
         Float_t ev_value=listsForBinning[icl][ivar].begin()->GetValue();
         Float_t lastev_value=ev_value;
         const Float_t eps = 1.e-4;
         vsForBinning[icl][ivar].push_back(ev_value-eps);
         vsForBinning[icl][ivar].push_back(ev_value);

         for (it=listsForBinning[icl][ivar].begin(); it != listsForBinning[icl][ivar].end(); it++){
            sum+= it->GetWeight();
            if (sum >= sumPerBin) {
               ev_value=it->GetValue();
               if (ev_value>lastev_value) {   // protection against bin width of 0
                  vsForBinning[icl][ivar].push_back(ev_value);
                  sum = 0.;
                  lastev_value=ev_value;
               }
            }
         }
         if (sum!=0) vsForBinning[icl][ivar].push_back(listsForBinning[icl][ivar].back().GetValue()); 
         nbins[icl][ivar] = vsForBinning[icl][ivar].size();
      }
   }

   delete[] sumOfWeights;
   delete[] minWeight;
   delete[] maxWeight;

   // create histogram for the cumulative distribution.
   fCumulativeDist.resize(inputSize);
   for (UInt_t icls = 0; icls < numDist; icls++) {
      for (UInt_t ivar=0; ivar < inputSize; ivar++){
         Float_t* binnings = new Float_t[nbins[icls][ivar]];
         //the binning for this particular histogram:
         for (UInt_t k =0 ; k < nbins[icls][ivar]; k++){
            binnings[k] = vsForBinning[icls][ivar][k];
         }
         fCumulativeDist[ivar].resize(numDist);         
         if (0 != fCumulativeDist[ivar][icls] ) {
            delete fCumulativeDist[ivar][icls]; 
         }
         fCumulativeDist[ivar][icls] = new TH1F(Form("Cumulative_Var%d_cls%d",ivar,icls),
                                                Form("Cumulative_Var%d_cls%d",ivar,icls),
                                                nbins[icls][ivar] -1, // class icls
                                                binnings);
         fCumulativeDist[ivar][icls]->SetDirectory(0);
         delete [] binnings;
      }
   }
   
   // Deallocation
   for (UInt_t i=0; i<numDist; i++) {
      delete [] listsForBinning[numDist-i-1];
      delete [] vsForBinning[numDist-i-1];
      delete [] nbins[numDist-i-1];
   }
   delete [] listsForBinning;
   delete [] vsForBinning;
   delete [] nbins;

   // perform event loop
   std::vector<Int_t> ic(numDist);
   for (UInt_t ievt=0; ievt<nevt; ievt++) {
      
      const Event* ev= events[ievt];
      Int_t cls = ev->GetClass();
      Float_t eventWeight = ev->GetWeight();
      
      GetInput( ev, input, mask );

      Int_t ivar = 0;
      for( std::vector<Float_t>::iterator itInput = input.begin(), itInputEnd = input.end(); itInput != itInputEnd; ++itInput ) {
	 Float_t value = (*itInput);
         fCumulativeDist[ivar][cls]->Fill(value,eventWeight);               
         if (numDist>1) fCumulativeDist[ivar][numDist-1]->Fill(value,eventWeight);               

	 ++ivar;
      }
   }         
   
   // clean up 
   CleanUpCumulativeArrays("PDF");

   // now sum up in order to get the real cumulative distribution   
   Double_t  sum = 0, total=0;
   fCumulativePDF.resize(inputSize);
   for (UInt_t ivar=0; ivar<inputSize; ivar++) {
//      fCumulativePDF.resize(ivar+1);
      for (UInt_t icls=0; icls<numDist; icls++) {      
         (fCumulativeDist[ivar][icls])->Smooth(); 
         sum = 0;
         total = 0.;
         for (Int_t ibin=1, ibinEnd=fCumulativeDist[ivar][icls]->GetNbinsX(); ibin <=ibinEnd ; ibin++){
            Float_t val = (fCumulativeDist[ivar][icls])->GetBinContent(ibin);
            if (val>0) total += val;
         }
         for (Int_t ibin=1, ibinEnd=fCumulativeDist[ivar][icls]->GetNbinsX(); ibin <=ibinEnd ; ibin++){
            Float_t val = (fCumulativeDist[ivar][icls])->GetBinContent(ibin);
            if (val>0) sum += val;
            (fCumulativeDist[ivar][icls])->SetBinContent(ibin,sum/total);
         }
         // create PDf
         fCumulativePDF[ivar].push_back(new PDF( Form("GaussTransform var%d cls%d",ivar,icls),  fCumulativeDist[ivar][icls], PDF::kSpline1, fPdfMinSmooth, fPdfMaxSmooth,kFALSE,kFALSE));
      }
   }
}

//_______________________________________________________________________
void TMVA::VariableGaussTransform::WriteTransformationToStream( std::ostream& ) const
{
   Log() << kFATAL << "VariableGaussTransform::WriteTransformationToStream is obsolete" << Endl; 
}

//_______________________________________________________________________
void TMVA::VariableGaussTransform::CleanUpCumulativeArrays(TString opt) {
   // clean up of cumulative arrays
   if (opt == "ALL" || opt == "PDF"){ 
      for (UInt_t ivar=0; ivar<fCumulativePDF.size(); ivar++) {
         for (UInt_t icls=0; icls<fCumulativePDF[ivar].size(); icls++) { 
            if (0 != fCumulativePDF[ivar][icls]) delete fCumulativePDF[ivar][icls];
         }
      }
      fCumulativePDF.clear();
   }
   if (opt == "ALL" || opt == "Dist"){ 
      for (UInt_t ivar=0; ivar<fCumulativeDist.size(); ivar++) {
         for (UInt_t icls=0; icls<fCumulativeDist[ivar].size(); icls++) { 
            if (0 != fCumulativeDist[ivar][icls]) delete fCumulativeDist[ivar][icls];
         }
      }
      fCumulativeDist.clear();
   }
}
//_______________________________________________________________________
void TMVA::VariableGaussTransform::AttachXMLTo(void* parent) {
   // create XML description of Gauss transformation
   void* trfxml = gTools().AddChild(parent, "Transform");
   gTools().AddAttr(trfxml, "Name",        "Gauss");
   gTools().AddAttr(trfxml, "FlatOrGauss", (fFlatNotGauss?"Flat":"Gauss") );

   VariableTransformBase::AttachXMLTo( trfxml );

   UInt_t nvar = fGet.size();
   for (UInt_t ivar=0; ivar<nvar; ivar++) {
      void* varxml = gTools().AddChild( trfxml, "Variable");
//      gTools().AddAttr( varxml, "Name",     Variables()[ivar].GetLabel() );
      gTools().AddAttr( varxml, "VarIndex", ivar );
         
      if ( fCumulativePDF[ivar][0]==0 || 
           (fCumulativePDF[ivar].size()>1 && fCumulativePDF[ivar][1]==0 ))
         Log() << kFATAL << "Cumulative histograms for variable " << ivar << " don't exist, can't write it to weight file" << Endl;
      
      for (UInt_t icls=0; icls<fCumulativePDF[ivar].size(); icls++){
         void* pdfxml = gTools().AddChild( varxml, Form("CumulativePDF_cls%d",icls));
         (fCumulativePDF[ivar][icls])->AddXMLTo(pdfxml);
      }
   }
}

//_______________________________________________________________________
void TMVA::VariableGaussTransform::ReadFromXML( void* trfnode ) {
   // Read the transformation matrices from the xml node

   // clean up first
   CleanUpCumulativeArrays();
   TString FlatOrGauss;

   gTools().ReadAttr(trfnode, "FlatOrGauss", FlatOrGauss );

   if (FlatOrGauss == "Flat") fFlatNotGauss = kTRUE;
   else                       fFlatNotGauss = kFALSE;

   Bool_t newFormat = kFALSE;

   void* inpnode = NULL;
   
   inpnode = gTools().GetChild(trfnode, "Selection"); // new xml format
   if( inpnode!=NULL )
      newFormat = kTRUE; // new xml format

   void* varnode = NULL;
   if( newFormat ){
      // ------------- new format --------------------
      // read input
      VariableTransformBase::ReadFromXML( inpnode );

      varnode = gTools().GetNextChild(inpnode);
   }else
      varnode = gTools().GetChild(trfnode);

   // Read the cumulative distribution

   TString varname, histname, classname;
   UInt_t ivar;
   while(varnode) {
      if( gTools().HasAttr(varnode,"Name") )
         gTools().ReadAttr(varnode, "Name", varname);
      gTools().ReadAttr(varnode, "VarIndex", ivar);
      
      void* clsnode = gTools().GetChild( varnode);

      while(clsnode) {
         void* pdfnode = gTools().GetChild( clsnode);
         PDF* pdfToRead = new PDF(TString("tempName"),kFALSE);
         pdfToRead->ReadXML(pdfnode); // pdfnode
         // push_back PDF
         fCumulativePDF.resize( ivar+1 );
         fCumulativePDF[ivar].push_back(pdfToRead);
         clsnode = gTools().GetNextChild(clsnode);
      }
      
      varnode = gTools().GetNextChild(varnode);    
   }
   SetCreated();
}

//_______________________________________________________________________
void TMVA::VariableGaussTransform::ReadTransformationFromStream( std::istream& istr, const TString& classname)
{
   // Read the cumulative distribution
   Bool_t addDirStatus = TH1::AddDirectoryStatus();
   TH1::AddDirectory(0); // this avoids the binding of the hists in TMVA::PDF to the current ROOT file
   char buf[512];
   istr.getline(buf,512);

   TString strvar, dummy;

   while (!(buf[0]=='#'&& buf[1]=='#')) { // if line starts with ## return
      char* p = buf;
      while (*p==' ' || *p=='\t') p++; // 'remove' leading whitespace
      if (*p=='#' || *p=='\0') {
         istr.getline(buf,512);
         continue; // if comment or empty line, read the next line
      }
      std::stringstream sstr(buf);
      sstr >> strvar;
      
      if (strvar=="CumulativeHistogram") {
         UInt_t  type(0), ivar(0);
         TString devnullS(""),hname("");
         Int_t   nbins(0);

         // coverity[tainted_data_argument]
         sstr  >> type >> ivar >> hname >> nbins >> fElementsperbin;

         Float_t *Binnings = new Float_t[nbins+1];
         Float_t val;
         istr >> devnullS; // read the line "BinBoundaries" ..
         for (Int_t ibin=0; ibin<nbins+1; ibin++) {
            istr >> val;
            Binnings[ibin]=val;
         }

         if(ivar>=fCumulativeDist.size()) fCumulativeDist.resize(ivar+1);
         if(type>=fCumulativeDist[ivar].size()) fCumulativeDist[ivar].resize(type+1);

         TH1F * histToRead = fCumulativeDist[ivar][type];
         if ( histToRead !=0 ) delete histToRead;
         // recreate the cumulative histogram to be filled with the values read
         histToRead = new TH1F( hname, hname, nbins, Binnings );
         histToRead->SetDirectory(0);
         fCumulativeDist[ivar][type]=histToRead;

         istr >> devnullS; // read the line "BinContent" .. 
         for (Int_t ibin=0; ibin<nbins; ibin++) {
            istr >> val;
            histToRead->SetBinContent(ibin+1,val);
         }

         PDF* pdf = new PDF(hname,histToRead,PDF::kSpline0, 0, 0, kFALSE, kFALSE);
         // push_back PDF
         fCumulativePDF.resize(ivar+1);
         fCumulativePDF[ivar].resize(type+1);
         fCumulativePDF[ivar][type] = pdf;
         delete [] Binnings;
      }

      //      if (strvar=="TransformToFlatInsetadOfGauss=") { // don't correct this spelling mistake
      if (strvar=="Uniform") { // don't correct this spelling mistake
         sstr >> fFlatNotGauss;
         istr.getline(buf,512);
         break;
      }

      istr.getline(buf,512); // reading the next line   
   }
   TH1::AddDirectory(addDirStatus);

   UInt_t classIdx=(classname=="signal")?0:1;
   for(UInt_t ivar=0; ivar<fCumulativePDF.size(); ++ivar) {
      PDF* src = fCumulativePDF[ivar][classIdx];
      fCumulativePDF[ivar].push_back(new PDF(src->GetName(),fCumulativeDist[ivar][classIdx],PDF::kSpline0, 0, 0, kFALSE, kFALSE) );
   }
   
   SetTMVAVersion(TMVA_VERSION(3,9,7));

   SetCreated();
}

Double_t TMVA::VariableGaussTransform::OldCumulant(Float_t x, TH1* h ) const {

   Int_t bin = h->FindBin(x);
   bin = TMath::Max(bin,1);
   bin = TMath::Min(bin,h->GetNbinsX());

   Double_t cumulant;
   Double_t x0, x1, y0, y1;
   Double_t total = h->GetNbinsX()*fElementsperbin;
   Double_t supmin = 0.5/total;
   
   x0 = h->GetBinLowEdge(TMath::Max(bin,1)); 
   x1 = h->GetBinLowEdge(TMath::Min(bin,h->GetNbinsX())+1); 

   y0 = h->GetBinContent(TMath::Max(bin-1,0)); // Y0 = F(x0); Y0 >= 0
   y1 = h->GetBinContent(TMath::Min(bin, h->GetNbinsX()+1));  // Y1 = F(x1);  Y1 <= 1

   if (bin == 0) {
      y0 = supmin;
      y1 = supmin;
   }
   if (bin == 1) {
      y0 = supmin;
   }
   if (bin > h->GetNbinsX()) { 
      y0 = 1.-supmin;
      y1 = 1.-supmin; 
   }
   if (bin == h->GetNbinsX()) { 
      y1 = 1.-supmin; 
   }

   if (x0 == x1) { 
      cumulant = y1;
   } else {
      cumulant = y0 + (y1-y0)*(x-x0)/(x1-x0);
   }

   if (x <= h->GetBinLowEdge(1)){
      cumulant = supmin;
   }
   if (x >= h->GetBinLowEdge(h->GetNbinsX()+1)){
      cumulant = 1-supmin;
   }
   return cumulant;
}



//_______________________________________________________________________
void TMVA::VariableGaussTransform::PrintTransformation( std::ostream& ) 
{
   // prints the transformation 
   Int_t cls = 0;
   Log() << kINFO << "I do not know yet how to print this... look in the weight file " << cls << ":" << Endl;
   cls++;
}

//_______________________________________________________________________
void TMVA::VariableGaussTransform::MakeFunction( std::ostream& fout, const TString& fcncName, 
                                                 Int_t part, UInt_t trCounter, Int_t ) 
{
   // creates the transformation function
   //
   const UInt_t nvar = fGet.size();
   UInt_t numDist  = GetNClasses() + 1;
   Int_t nBins = -1; 
   for (UInt_t icls=0; icls<numDist; icls++) {
      for (UInt_t ivar=0; ivar<nvar; ivar++) {
         Int_t nbin=(fCumulativePDF[ivar][icls])->GetGraph()->GetN();
         if (nbin > nBins) nBins=nbin;
      }
   }

   // creates the gauss transformation function
   if (part==1) {
      fout << std::endl;
      fout << "   int nvar;" << std::endl;
      fout << std::endl;
      // declare variables
      fout << "   double  cumulativeDist["<<nvar<<"]["<<numDist<<"]["<<nBins+1<<"];"<<std::endl;
      fout << "   double  X["<<nvar<<"]["<<numDist<<"]["<<nBins+1<<"];"<<std::endl;
      fout << "   double xMin["<<nvar<<"]["<<numDist<<"];"<<std::endl;
      fout << "   double xMax["<<nvar<<"]["<<numDist<<"];"<<std::endl;
      fout << "   int    nbins["<<nvar<<"]["<<numDist<<"];"<<std::endl;
   }
   if (part==2) {
      fout << std::endl;
      fout << "#include \"math.h\"" << std::endl;
      fout << std::endl;
      fout << "//_______________________________________________________________________" << std::endl;
      fout << "inline void " << fcncName << "::InitTransform_"<<trCounter<<"()" << std::endl;
      fout << "{" << std::endl;
      fout << "   // Gauss/Uniform transformation, initialisation" << std::endl;
      fout << "   nvar=" << nvar << ";" << std::endl;
      for (UInt_t icls=0; icls<numDist; icls++) {
         for (UInt_t ivar=0; ivar<nvar; ivar++) {
            Int_t nbin=(fCumulativePDF[ivar][icls])->GetGraph()->GetN();
            fout << "   nbins["<<ivar<<"]["<<icls<<"]="<<nbin<<";"<<std::endl;
         }
      }

      // fill meat here
      // loop over nvar , cls, loop over nBins
      // fill cumulativeDist with fCumulativePDF[ivar][cls])->GetValue(vec(ivar)
      for (UInt_t icls=0; icls<numDist; icls++) {
         for (UInt_t ivar=0; ivar<nvar; ivar++) {
            // Int_t idx = 0;
            try{
               // idx = fGet.at(ivar).second;
               Char_t type = fGet.at(ivar).first;
               if( type != 'v' ){
                  Log() << kWARNING << "MakeClass for the Gauss transformation works only for the transformation of variables. The transformation of targets/spectators is not implemented." << Endl;
               }
            }catch( std::out_of_range except ){
               Log() << kWARNING << "MakeClass for the Gauss transformation searched for a non existing variable index (" << ivar << ")" << Endl;
            } 

//            Double_t xmn=Variables()[idx].GetMin();
//            Double_t xmx=Variables()[idx].GetMax();
            Double_t xmn = (fCumulativePDF[ivar][icls])->GetGraph()->GetX()[0];
            Double_t xmx = (fCumulativePDF[ivar][icls])->GetGraph()->GetX()[(fCumulativePDF[ivar][icls])->GetGraph()->GetN()-1];

            fout << "    xMin["<<ivar<<"]["<<icls<<"]="<< gTools().StringFromDouble(xmn)<<";"<<std::endl;
            fout << "    xMax["<<ivar<<"]["<<icls<<"]="<<gTools().StringFromDouble(xmx)<<";"<<std::endl;
            for (Int_t ibin=0; ibin<(fCumulativePDF[ivar][icls])->GetGraph()->GetN(); ibin++) {
               fout << "  cumulativeDist[" << ivar << "]["<< icls<< "]["<<ibin<<"]="<< gTools().StringFromDouble((fCumulativePDF[ivar][icls])->GetGraph()->GetY()[ibin])<< ";"<<std::endl;
                                                                                        fout << "  X[" << ivar << "]["<< icls<< "]["<<ibin<<"]="<< gTools().StringFromDouble((fCumulativePDF[ivar][icls])->GetGraph()->GetX()[ibin])<< ";"<<std::endl;

            }
         }
      }
      fout << "}" << std::endl;
      fout << std::endl;
      fout << "//_______________________________________________________________________" << std::endl;
      fout << "inline void " << fcncName << "::Transform_"<<trCounter<<"( std::vector<double>& iv, int clsIn) const" << std::endl;
      fout << "{" << std::endl;
      fout << "   // Gauss/Uniform transformation" << std::endl;
      fout << "   int cls=clsIn;" << std::endl;
      fout << "   if (cls < 0 || cls > "<<GetNClasses()<<") {"<< std::endl;
      fout << "       if ("<<GetNClasses()<<" > 1 ) cls = "<<GetNClasses()<<";"<< std::endl;
      fout << "       else cls = "<<(fCumulativePDF[0].size()==1?0:2)<<";"<< std::endl;
      fout << "   }"<< std::endl;
      
      fout << "   // copy the variables which are going to be transformed                                "<< std::endl;
      VariableTransformBase::MakeFunction(fout, fcncName, 0, trCounter, 0 );
      fout << "   static std::vector<double> dv;                                                          "<< std::endl;
      fout << "   dv.resize(nvar);                                                                       "<< std::endl;
      fout << "   for (int ivar=0; ivar<nvar; ivar++) dv[ivar] = iv[indicesGet.at(ivar)];                "<< std::endl;
      fout << "                                                                                          "<< std::endl;
      fout << "   bool FlatNotGauss = "<< (fFlatNotGauss? "true": "false") <<";                          "<< std::endl;
      fout << "   double cumulant;                                                                       "<< std::endl;
      fout << "   //const int nvar = "<<nvar<<";                                                         "<< std::endl;
      fout << "   for (int ivar=0; ivar<nvar; ivar++) {                                                  "<< std::endl;
      fout << "      int nbin  = nbins[ivar][cls];                                                       "<< std::endl;
      fout << "      int ibin=0;                                                                         "<< std::endl;
      fout << "      while (dv[ivar] > X[ivar][cls][ibin]) ibin++;                                       "<< std::endl;
      fout << "                                                                                          "<< std::endl;
      fout << "      if (ibin<0) { ibin=0;}                                                              "<< std::endl;
      fout << "      if (ibin>=nbin) { ibin=nbin-1;}                                                     "<< std::endl;
      fout << "      int nextbin = ibin;                                                                 "<< std::endl;
      fout << "      if ((dv[ivar] > X[ivar][cls][ibin] && ibin !=nbin-1) || ibin==0)                    "<< std::endl;
      fout << "         nextbin++;                                                                       "<< std::endl;
      fout << "      else                                                                                "<< std::endl;
      fout << "         nextbin--;                                                                       "<< std::endl;
      fout << "                                                                                          "<< std::endl;
      fout << "      double dx = X[ivar][cls][ibin]- X[ivar][cls][nextbin];                              "<< std::endl;
      fout << "      double dy = cumulativeDist[ivar][cls][ibin] - cumulativeDist[ivar][cls][nextbin];   "<< std::endl;
      fout << "      cumulant = cumulativeDist[ivar][cls][ibin] + (dv[ivar] - X[ivar][cls][ibin])* dy/dx;"<< std::endl;
      fout << "                                                                                          "<< std::endl;
      fout << "                                                                                          "<< std::endl;
      fout << "      if (cumulant>1.-10e-10) cumulant = 1.-10e-10;                                       "<< std::endl;
      fout << "      if (cumulant<10e-10)    cumulant = 10e-10;                                          "<< std::endl;
      fout << "      if (FlatNotGauss) dv[ivar] = cumulant;                                              "<< std::endl;
      fout << "      else {                                                                              "<< std::endl;
      fout << "         double maxErfInvArgRange = 0.99999999;                                           "<< std::endl;
      fout << "         double arg = 2.0*cumulant - 1.0;                                                 "<< std::endl;
      fout << "         if (arg >  maxErfInvArgRange) arg= maxErfInvArgRange;                            "<< std::endl;
      fout << "         if (arg < -maxErfInvArgRange) arg=-maxErfInvArgRange;                            "<< std::endl;
      fout << "         double inverf=0., stp=1. ;                                                       "<< std::endl;
      fout << "         while (stp >1.e-10){;                                                            "<< std::endl;
      fout << "            if (erf(inverf)>arg) inverf -=stp ;                                           "<< std::endl;
      fout << "            else if (erf(inverf)<=arg && erf(inverf+stp)>=arg) stp=stp/5. ;               "<< std::endl;
      fout << "            else inverf += stp;                                                           "<< std::endl;
      fout << "         } ;                                                                              "<< std::endl;
      fout << "         //dv[ivar] = 1.414213562*TMath::ErfInverse(arg);                                 "<< std::endl;
      fout << "         dv[ivar] = 1.414213562* inverf;                                                  "<< std::endl;
      fout << "      }                                                                                   "<< std::endl;
      fout << "   }                                                                                      "<< std::endl;
      fout << "   // copy the transformed variables back                                                 "<< std::endl;
      fout << "   for (int ivar=0; ivar<nvar; ivar++) iv[indicesPut.at(ivar)] = dv[ivar];                "<< std::endl;
      fout << "}                                                                                         "<< std::endl;
   }
}
 VariableGaussTransform.cxx:1
 VariableGaussTransform.cxx:2
 VariableGaussTransform.cxx:3
 VariableGaussTransform.cxx:4
 VariableGaussTransform.cxx:5
 VariableGaussTransform.cxx:6
 VariableGaussTransform.cxx:7
 VariableGaussTransform.cxx:8
 VariableGaussTransform.cxx:9
 VariableGaussTransform.cxx:10
 VariableGaussTransform.cxx:11
 VariableGaussTransform.cxx:12
 VariableGaussTransform.cxx:13
 VariableGaussTransform.cxx:14
 VariableGaussTransform.cxx:15
 VariableGaussTransform.cxx:16
 VariableGaussTransform.cxx:17
 VariableGaussTransform.cxx:18
 VariableGaussTransform.cxx:19
 VariableGaussTransform.cxx:20
 VariableGaussTransform.cxx:21
 VariableGaussTransform.cxx:22
 VariableGaussTransform.cxx:23
 VariableGaussTransform.cxx:24
 VariableGaussTransform.cxx:25
 VariableGaussTransform.cxx:26
 VariableGaussTransform.cxx:27
 VariableGaussTransform.cxx:28
 VariableGaussTransform.cxx:29
 VariableGaussTransform.cxx:30
 VariableGaussTransform.cxx:31
 VariableGaussTransform.cxx:32
 VariableGaussTransform.cxx:33
 VariableGaussTransform.cxx:34
 VariableGaussTransform.cxx:35
 VariableGaussTransform.cxx:36
 VariableGaussTransform.cxx:37
 VariableGaussTransform.cxx:38
 VariableGaussTransform.cxx:39
 VariableGaussTransform.cxx:40
 VariableGaussTransform.cxx:41
 VariableGaussTransform.cxx:42
 VariableGaussTransform.cxx:43
 VariableGaussTransform.cxx:44
 VariableGaussTransform.cxx:45
 VariableGaussTransform.cxx:46
 VariableGaussTransform.cxx:47
 VariableGaussTransform.cxx:48
 VariableGaussTransform.cxx:49
 VariableGaussTransform.cxx:50
 VariableGaussTransform.cxx:51
 VariableGaussTransform.cxx:52
 VariableGaussTransform.cxx:53
 VariableGaussTransform.cxx:54
 VariableGaussTransform.cxx:55
 VariableGaussTransform.cxx:56
 VariableGaussTransform.cxx:57
 VariableGaussTransform.cxx:58
 VariableGaussTransform.cxx:59
 VariableGaussTransform.cxx:60
 VariableGaussTransform.cxx:61
 VariableGaussTransform.cxx:62
 VariableGaussTransform.cxx:63
 VariableGaussTransform.cxx:64
 VariableGaussTransform.cxx:65
 VariableGaussTransform.cxx:66
 VariableGaussTransform.cxx:67
 VariableGaussTransform.cxx:68
 VariableGaussTransform.cxx:69
 VariableGaussTransform.cxx:70
 VariableGaussTransform.cxx:71
 VariableGaussTransform.cxx:72
 VariableGaussTransform.cxx:73
 VariableGaussTransform.cxx:74
 VariableGaussTransform.cxx:75
 VariableGaussTransform.cxx:76
 VariableGaussTransform.cxx:77
 VariableGaussTransform.cxx:78
 VariableGaussTransform.cxx:79
 VariableGaussTransform.cxx:80
 VariableGaussTransform.cxx:81
 VariableGaussTransform.cxx:82
 VariableGaussTransform.cxx:83
 VariableGaussTransform.cxx:84
 VariableGaussTransform.cxx:85
 VariableGaussTransform.cxx:86
 VariableGaussTransform.cxx:87
 VariableGaussTransform.cxx:88
 VariableGaussTransform.cxx:89
 VariableGaussTransform.cxx:90
 VariableGaussTransform.cxx:91
 VariableGaussTransform.cxx:92
 VariableGaussTransform.cxx:93
 VariableGaussTransform.cxx:94
 VariableGaussTransform.cxx:95
 VariableGaussTransform.cxx:96
 VariableGaussTransform.cxx:97
 VariableGaussTransform.cxx:98
 VariableGaussTransform.cxx:99
 VariableGaussTransform.cxx:100
 VariableGaussTransform.cxx:101
 VariableGaussTransform.cxx:102
 VariableGaussTransform.cxx:103
 VariableGaussTransform.cxx:104
 VariableGaussTransform.cxx:105
 VariableGaussTransform.cxx:106
 VariableGaussTransform.cxx:107
 VariableGaussTransform.cxx:108
 VariableGaussTransform.cxx:109
 VariableGaussTransform.cxx:110
 VariableGaussTransform.cxx:111
 VariableGaussTransform.cxx:112
 VariableGaussTransform.cxx:113
 VariableGaussTransform.cxx:114
 VariableGaussTransform.cxx:115
 VariableGaussTransform.cxx:116
 VariableGaussTransform.cxx:117
 VariableGaussTransform.cxx:118
 VariableGaussTransform.cxx:119
 VariableGaussTransform.cxx:120
 VariableGaussTransform.cxx:121
 VariableGaussTransform.cxx:122
 VariableGaussTransform.cxx:123
 VariableGaussTransform.cxx:124
 VariableGaussTransform.cxx:125
 VariableGaussTransform.cxx:126
 VariableGaussTransform.cxx:127
 VariableGaussTransform.cxx:128
 VariableGaussTransform.cxx:129
 VariableGaussTransform.cxx:130
 VariableGaussTransform.cxx:131
 VariableGaussTransform.cxx:132
 VariableGaussTransform.cxx:133
 VariableGaussTransform.cxx:134
 VariableGaussTransform.cxx:135
 VariableGaussTransform.cxx:136
 VariableGaussTransform.cxx:137
 VariableGaussTransform.cxx:138
 VariableGaussTransform.cxx:139
 VariableGaussTransform.cxx:140
 VariableGaussTransform.cxx:141
 VariableGaussTransform.cxx:142
 VariableGaussTransform.cxx:143
 VariableGaussTransform.cxx:144
 VariableGaussTransform.cxx:145
 VariableGaussTransform.cxx:146
 VariableGaussTransform.cxx:147
 VariableGaussTransform.cxx:148
 VariableGaussTransform.cxx:149
 VariableGaussTransform.cxx:150
 VariableGaussTransform.cxx:151
 VariableGaussTransform.cxx:152
 VariableGaussTransform.cxx:153
 VariableGaussTransform.cxx:154
 VariableGaussTransform.cxx:155
 VariableGaussTransform.cxx:156
 VariableGaussTransform.cxx:157
 VariableGaussTransform.cxx:158
 VariableGaussTransform.cxx:159
 VariableGaussTransform.cxx:160
 VariableGaussTransform.cxx:161
 VariableGaussTransform.cxx:162
 VariableGaussTransform.cxx:163
 VariableGaussTransform.cxx:164
 VariableGaussTransform.cxx:165
 VariableGaussTransform.cxx:166
 VariableGaussTransform.cxx:167
 VariableGaussTransform.cxx:168
 VariableGaussTransform.cxx:169
 VariableGaussTransform.cxx:170
 VariableGaussTransform.cxx:171
 VariableGaussTransform.cxx:172
 VariableGaussTransform.cxx:173
 VariableGaussTransform.cxx:174
 VariableGaussTransform.cxx:175
 VariableGaussTransform.cxx:176
 VariableGaussTransform.cxx:177
 VariableGaussTransform.cxx:178
 VariableGaussTransform.cxx:179
 VariableGaussTransform.cxx:180
 VariableGaussTransform.cxx:181
 VariableGaussTransform.cxx:182
 VariableGaussTransform.cxx:183
 VariableGaussTransform.cxx:184
 VariableGaussTransform.cxx:185
 VariableGaussTransform.cxx:186
 VariableGaussTransform.cxx:187
 VariableGaussTransform.cxx:188
 VariableGaussTransform.cxx:189
 VariableGaussTransform.cxx:190
 VariableGaussTransform.cxx:191
 VariableGaussTransform.cxx:192
 VariableGaussTransform.cxx:193
 VariableGaussTransform.cxx:194
 VariableGaussTransform.cxx:195
 VariableGaussTransform.cxx:196
 VariableGaussTransform.cxx:197
 VariableGaussTransform.cxx:198
 VariableGaussTransform.cxx:199
 VariableGaussTransform.cxx:200
 VariableGaussTransform.cxx:201
 VariableGaussTransform.cxx:202
 VariableGaussTransform.cxx:203
 VariableGaussTransform.cxx:204
 VariableGaussTransform.cxx:205
 VariableGaussTransform.cxx:206
 VariableGaussTransform.cxx:207
 VariableGaussTransform.cxx:208
 VariableGaussTransform.cxx:209
 VariableGaussTransform.cxx:210
 VariableGaussTransform.cxx:211
 VariableGaussTransform.cxx:212
 VariableGaussTransform.cxx:213
 VariableGaussTransform.cxx:214
 VariableGaussTransform.cxx:215
 VariableGaussTransform.cxx:216
 VariableGaussTransform.cxx:217
 VariableGaussTransform.cxx:218
 VariableGaussTransform.cxx:219
 VariableGaussTransform.cxx:220
 VariableGaussTransform.cxx:221
 VariableGaussTransform.cxx:222
 VariableGaussTransform.cxx:223
 VariableGaussTransform.cxx:224
 VariableGaussTransform.cxx:225
 VariableGaussTransform.cxx:226
 VariableGaussTransform.cxx:227
 VariableGaussTransform.cxx:228
 VariableGaussTransform.cxx:229
 VariableGaussTransform.cxx:230
 VariableGaussTransform.cxx:231
 VariableGaussTransform.cxx:232
 VariableGaussTransform.cxx:233
 VariableGaussTransform.cxx:234
 VariableGaussTransform.cxx:235
 VariableGaussTransform.cxx:236
 VariableGaussTransform.cxx:237
 VariableGaussTransform.cxx:238
 VariableGaussTransform.cxx:239
 VariableGaussTransform.cxx:240
 VariableGaussTransform.cxx:241
 VariableGaussTransform.cxx:242
 VariableGaussTransform.cxx:243
 VariableGaussTransform.cxx:244
 VariableGaussTransform.cxx:245
 VariableGaussTransform.cxx:246
 VariableGaussTransform.cxx:247
 VariableGaussTransform.cxx:248
 VariableGaussTransform.cxx:249
 VariableGaussTransform.cxx:250
 VariableGaussTransform.cxx:251
 VariableGaussTransform.cxx:252
 VariableGaussTransform.cxx:253
 VariableGaussTransform.cxx:254
 VariableGaussTransform.cxx:255
 VariableGaussTransform.cxx:256
 VariableGaussTransform.cxx:257
 VariableGaussTransform.cxx:258
 VariableGaussTransform.cxx:259
 VariableGaussTransform.cxx:260
 VariableGaussTransform.cxx:261
 VariableGaussTransform.cxx:262
 VariableGaussTransform.cxx:263
 VariableGaussTransform.cxx:264
 VariableGaussTransform.cxx:265
 VariableGaussTransform.cxx:266
 VariableGaussTransform.cxx:267
 VariableGaussTransform.cxx:268
 VariableGaussTransform.cxx:269
 VariableGaussTransform.cxx:270
 VariableGaussTransform.cxx:271
 VariableGaussTransform.cxx:272
 VariableGaussTransform.cxx:273
 VariableGaussTransform.cxx:274
 VariableGaussTransform.cxx:275
 VariableGaussTransform.cxx:276
 VariableGaussTransform.cxx:277
 VariableGaussTransform.cxx:278
 VariableGaussTransform.cxx:279
 VariableGaussTransform.cxx:280
 VariableGaussTransform.cxx:281
 VariableGaussTransform.cxx:282
 VariableGaussTransform.cxx:283
 VariableGaussTransform.cxx:284
 VariableGaussTransform.cxx:285
 VariableGaussTransform.cxx:286
 VariableGaussTransform.cxx:287
 VariableGaussTransform.cxx:288
 VariableGaussTransform.cxx:289
 VariableGaussTransform.cxx:290
 VariableGaussTransform.cxx:291
 VariableGaussTransform.cxx:292
 VariableGaussTransform.cxx:293
 VariableGaussTransform.cxx:294
 VariableGaussTransform.cxx:295
 VariableGaussTransform.cxx:296
 VariableGaussTransform.cxx:297
 VariableGaussTransform.cxx:298
 VariableGaussTransform.cxx:299
 VariableGaussTransform.cxx:300
 VariableGaussTransform.cxx:301
 VariableGaussTransform.cxx:302
 VariableGaussTransform.cxx:303
 VariableGaussTransform.cxx:304
 VariableGaussTransform.cxx:305
 VariableGaussTransform.cxx:306
 VariableGaussTransform.cxx:307
 VariableGaussTransform.cxx:308
 VariableGaussTransform.cxx:309
 VariableGaussTransform.cxx:310
 VariableGaussTransform.cxx:311
 VariableGaussTransform.cxx:312
 VariableGaussTransform.cxx:313
 VariableGaussTransform.cxx:314
 VariableGaussTransform.cxx:315
 VariableGaussTransform.cxx:316
 VariableGaussTransform.cxx:317
 VariableGaussTransform.cxx:318
 VariableGaussTransform.cxx:319
 VariableGaussTransform.cxx:320
 VariableGaussTransform.cxx:321
 VariableGaussTransform.cxx:322
 VariableGaussTransform.cxx:323
 VariableGaussTransform.cxx:324
 VariableGaussTransform.cxx:325
 VariableGaussTransform.cxx:326
 VariableGaussTransform.cxx:327
 VariableGaussTransform.cxx:328
 VariableGaussTransform.cxx:329
 VariableGaussTransform.cxx:330
 VariableGaussTransform.cxx:331
 VariableGaussTransform.cxx:332
 VariableGaussTransform.cxx:333
 VariableGaussTransform.cxx:334
 VariableGaussTransform.cxx:335
 VariableGaussTransform.cxx:336
 VariableGaussTransform.cxx:337
 VariableGaussTransform.cxx:338
 VariableGaussTransform.cxx:339
 VariableGaussTransform.cxx:340
 VariableGaussTransform.cxx:341
 VariableGaussTransform.cxx:342
 VariableGaussTransform.cxx:343
 VariableGaussTransform.cxx:344
 VariableGaussTransform.cxx:345
 VariableGaussTransform.cxx:346
 VariableGaussTransform.cxx:347
 VariableGaussTransform.cxx:348
 VariableGaussTransform.cxx:349
 VariableGaussTransform.cxx:350
 VariableGaussTransform.cxx:351
 VariableGaussTransform.cxx:352
 VariableGaussTransform.cxx:353
 VariableGaussTransform.cxx:354
 VariableGaussTransform.cxx:355
 VariableGaussTransform.cxx:356
 VariableGaussTransform.cxx:357
 VariableGaussTransform.cxx:358
 VariableGaussTransform.cxx:359
 VariableGaussTransform.cxx:360
 VariableGaussTransform.cxx:361
 VariableGaussTransform.cxx:362
 VariableGaussTransform.cxx:363
 VariableGaussTransform.cxx:364
 VariableGaussTransform.cxx:365
 VariableGaussTransform.cxx:366
 VariableGaussTransform.cxx:367
 VariableGaussTransform.cxx:368
 VariableGaussTransform.cxx:369
 VariableGaussTransform.cxx:370
 VariableGaussTransform.cxx:371
 VariableGaussTransform.cxx:372
 VariableGaussTransform.cxx:373
 VariableGaussTransform.cxx:374
 VariableGaussTransform.cxx:375
 VariableGaussTransform.cxx:376
 VariableGaussTransform.cxx:377
 VariableGaussTransform.cxx:378
 VariableGaussTransform.cxx:379
 VariableGaussTransform.cxx:380
 VariableGaussTransform.cxx:381
 VariableGaussTransform.cxx:382
 VariableGaussTransform.cxx:383
 VariableGaussTransform.cxx:384
 VariableGaussTransform.cxx:385
 VariableGaussTransform.cxx:386
 VariableGaussTransform.cxx:387
 VariableGaussTransform.cxx:388
 VariableGaussTransform.cxx:389
 VariableGaussTransform.cxx:390
 VariableGaussTransform.cxx:391
 VariableGaussTransform.cxx:392
 VariableGaussTransform.cxx:393
 VariableGaussTransform.cxx:394
 VariableGaussTransform.cxx:395
 VariableGaussTransform.cxx:396
 VariableGaussTransform.cxx:397
 VariableGaussTransform.cxx:398
 VariableGaussTransform.cxx:399
 VariableGaussTransform.cxx:400
 VariableGaussTransform.cxx:401
 VariableGaussTransform.cxx:402
 VariableGaussTransform.cxx:403
 VariableGaussTransform.cxx:404
 VariableGaussTransform.cxx:405
 VariableGaussTransform.cxx:406
 VariableGaussTransform.cxx:407
 VariableGaussTransform.cxx:408
 VariableGaussTransform.cxx:409
 VariableGaussTransform.cxx:410
 VariableGaussTransform.cxx:411
 VariableGaussTransform.cxx:412
 VariableGaussTransform.cxx:413
 VariableGaussTransform.cxx:414
 VariableGaussTransform.cxx:415
 VariableGaussTransform.cxx:416
 VariableGaussTransform.cxx:417
 VariableGaussTransform.cxx:418
 VariableGaussTransform.cxx:419
 VariableGaussTransform.cxx:420
 VariableGaussTransform.cxx:421
 VariableGaussTransform.cxx:422
 VariableGaussTransform.cxx:423
 VariableGaussTransform.cxx:424
 VariableGaussTransform.cxx:425
 VariableGaussTransform.cxx:426
 VariableGaussTransform.cxx:427
 VariableGaussTransform.cxx:428
 VariableGaussTransform.cxx:429
 VariableGaussTransform.cxx:430
 VariableGaussTransform.cxx:431
 VariableGaussTransform.cxx:432
 VariableGaussTransform.cxx:433
 VariableGaussTransform.cxx:434
 VariableGaussTransform.cxx:435
 VariableGaussTransform.cxx:436
 VariableGaussTransform.cxx:437
 VariableGaussTransform.cxx:438
 VariableGaussTransform.cxx:439
 VariableGaussTransform.cxx:440
 VariableGaussTransform.cxx:441
 VariableGaussTransform.cxx:442
 VariableGaussTransform.cxx:443
 VariableGaussTransform.cxx:444
 VariableGaussTransform.cxx:445
 VariableGaussTransform.cxx:446
 VariableGaussTransform.cxx:447
 VariableGaussTransform.cxx:448
 VariableGaussTransform.cxx:449
 VariableGaussTransform.cxx:450
 VariableGaussTransform.cxx:451
 VariableGaussTransform.cxx:452
 VariableGaussTransform.cxx:453
 VariableGaussTransform.cxx:454
 VariableGaussTransform.cxx:455
 VariableGaussTransform.cxx:456
 VariableGaussTransform.cxx:457
 VariableGaussTransform.cxx:458
 VariableGaussTransform.cxx:459
 VariableGaussTransform.cxx:460
 VariableGaussTransform.cxx:461
 VariableGaussTransform.cxx:462
 VariableGaussTransform.cxx:463
 VariableGaussTransform.cxx:464
 VariableGaussTransform.cxx:465
 VariableGaussTransform.cxx:466
 VariableGaussTransform.cxx:467
 VariableGaussTransform.cxx:468
 VariableGaussTransform.cxx:469
 VariableGaussTransform.cxx:470
 VariableGaussTransform.cxx:471
 VariableGaussTransform.cxx:472
 VariableGaussTransform.cxx:473
 VariableGaussTransform.cxx:474
 VariableGaussTransform.cxx:475
 VariableGaussTransform.cxx:476
 VariableGaussTransform.cxx:477
 VariableGaussTransform.cxx:478
 VariableGaussTransform.cxx:479
 VariableGaussTransform.cxx:480
 VariableGaussTransform.cxx:481
 VariableGaussTransform.cxx:482
 VariableGaussTransform.cxx:483
 VariableGaussTransform.cxx:484
 VariableGaussTransform.cxx:485
 VariableGaussTransform.cxx:486
 VariableGaussTransform.cxx:487
 VariableGaussTransform.cxx:488
 VariableGaussTransform.cxx:489
 VariableGaussTransform.cxx:490
 VariableGaussTransform.cxx:491
 VariableGaussTransform.cxx:492
 VariableGaussTransform.cxx:493
 VariableGaussTransform.cxx:494
 VariableGaussTransform.cxx:495
 VariableGaussTransform.cxx:496
 VariableGaussTransform.cxx:497
 VariableGaussTransform.cxx:498
 VariableGaussTransform.cxx:499
 VariableGaussTransform.cxx:500
 VariableGaussTransform.cxx:501
 VariableGaussTransform.cxx:502
 VariableGaussTransform.cxx:503
 VariableGaussTransform.cxx:504
 VariableGaussTransform.cxx:505
 VariableGaussTransform.cxx:506
 VariableGaussTransform.cxx:507
 VariableGaussTransform.cxx:508
 VariableGaussTransform.cxx:509
 VariableGaussTransform.cxx:510
 VariableGaussTransform.cxx:511
 VariableGaussTransform.cxx:512
 VariableGaussTransform.cxx:513
 VariableGaussTransform.cxx:514
 VariableGaussTransform.cxx:515
 VariableGaussTransform.cxx:516
 VariableGaussTransform.cxx:517
 VariableGaussTransform.cxx:518
 VariableGaussTransform.cxx:519
 VariableGaussTransform.cxx:520
 VariableGaussTransform.cxx:521
 VariableGaussTransform.cxx:522
 VariableGaussTransform.cxx:523
 VariableGaussTransform.cxx:524
 VariableGaussTransform.cxx:525
 VariableGaussTransform.cxx:526
 VariableGaussTransform.cxx:527
 VariableGaussTransform.cxx:528
 VariableGaussTransform.cxx:529
 VariableGaussTransform.cxx:530
 VariableGaussTransform.cxx:531
 VariableGaussTransform.cxx:532
 VariableGaussTransform.cxx:533
 VariableGaussTransform.cxx:534
 VariableGaussTransform.cxx:535
 VariableGaussTransform.cxx:536
 VariableGaussTransform.cxx:537
 VariableGaussTransform.cxx:538
 VariableGaussTransform.cxx:539
 VariableGaussTransform.cxx:540
 VariableGaussTransform.cxx:541
 VariableGaussTransform.cxx:542
 VariableGaussTransform.cxx:543
 VariableGaussTransform.cxx:544
 VariableGaussTransform.cxx:545
 VariableGaussTransform.cxx:546
 VariableGaussTransform.cxx:547
 VariableGaussTransform.cxx:548
 VariableGaussTransform.cxx:549
 VariableGaussTransform.cxx:550
 VariableGaussTransform.cxx:551
 VariableGaussTransform.cxx:552
 VariableGaussTransform.cxx:553
 VariableGaussTransform.cxx:554
 VariableGaussTransform.cxx:555
 VariableGaussTransform.cxx:556
 VariableGaussTransform.cxx:557
 VariableGaussTransform.cxx:558
 VariableGaussTransform.cxx:559
 VariableGaussTransform.cxx:560
 VariableGaussTransform.cxx:561
 VariableGaussTransform.cxx:562
 VariableGaussTransform.cxx:563
 VariableGaussTransform.cxx:564
 VariableGaussTransform.cxx:565
 VariableGaussTransform.cxx:566
 VariableGaussTransform.cxx:567
 VariableGaussTransform.cxx:568
 VariableGaussTransform.cxx:569
 VariableGaussTransform.cxx:570
 VariableGaussTransform.cxx:571
 VariableGaussTransform.cxx:572
 VariableGaussTransform.cxx:573
 VariableGaussTransform.cxx:574
 VariableGaussTransform.cxx:575
 VariableGaussTransform.cxx:576
 VariableGaussTransform.cxx:577
 VariableGaussTransform.cxx:578
 VariableGaussTransform.cxx:579
 VariableGaussTransform.cxx:580
 VariableGaussTransform.cxx:581
 VariableGaussTransform.cxx:582
 VariableGaussTransform.cxx:583
 VariableGaussTransform.cxx:584
 VariableGaussTransform.cxx:585
 VariableGaussTransform.cxx:586
 VariableGaussTransform.cxx:587
 VariableGaussTransform.cxx:588
 VariableGaussTransform.cxx:589
 VariableGaussTransform.cxx:590
 VariableGaussTransform.cxx:591
 VariableGaussTransform.cxx:592
 VariableGaussTransform.cxx:593
 VariableGaussTransform.cxx:594
 VariableGaussTransform.cxx:595
 VariableGaussTransform.cxx:596
 VariableGaussTransform.cxx:597
 VariableGaussTransform.cxx:598
 VariableGaussTransform.cxx:599
 VariableGaussTransform.cxx:600
 VariableGaussTransform.cxx:601
 VariableGaussTransform.cxx:602
 VariableGaussTransform.cxx:603
 VariableGaussTransform.cxx:604
 VariableGaussTransform.cxx:605
 VariableGaussTransform.cxx:606
 VariableGaussTransform.cxx:607
 VariableGaussTransform.cxx:608
 VariableGaussTransform.cxx:609
 VariableGaussTransform.cxx:610
 VariableGaussTransform.cxx:611
 VariableGaussTransform.cxx:612
 VariableGaussTransform.cxx:613
 VariableGaussTransform.cxx:614
 VariableGaussTransform.cxx:615
 VariableGaussTransform.cxx:616
 VariableGaussTransform.cxx:617
 VariableGaussTransform.cxx:618
 VariableGaussTransform.cxx:619
 VariableGaussTransform.cxx:620
 VariableGaussTransform.cxx:621
 VariableGaussTransform.cxx:622
 VariableGaussTransform.cxx:623
 VariableGaussTransform.cxx:624
 VariableGaussTransform.cxx:625
 VariableGaussTransform.cxx:626
 VariableGaussTransform.cxx:627
 VariableGaussTransform.cxx:628
 VariableGaussTransform.cxx:629
 VariableGaussTransform.cxx:630
 VariableGaussTransform.cxx:631
 VariableGaussTransform.cxx:632
 VariableGaussTransform.cxx:633
 VariableGaussTransform.cxx:634
 VariableGaussTransform.cxx:635
 VariableGaussTransform.cxx:636
 VariableGaussTransform.cxx:637
 VariableGaussTransform.cxx:638
 VariableGaussTransform.cxx:639
 VariableGaussTransform.cxx:640
 VariableGaussTransform.cxx:641
 VariableGaussTransform.cxx:642
 VariableGaussTransform.cxx:643
 VariableGaussTransform.cxx:644
 VariableGaussTransform.cxx:645
 VariableGaussTransform.cxx:646
 VariableGaussTransform.cxx:647
 VariableGaussTransform.cxx:648
 VariableGaussTransform.cxx:649
 VariableGaussTransform.cxx:650
 VariableGaussTransform.cxx:651
 VariableGaussTransform.cxx:652
 VariableGaussTransform.cxx:653
 VariableGaussTransform.cxx:654
 VariableGaussTransform.cxx:655
 VariableGaussTransform.cxx:656
 VariableGaussTransform.cxx:657
 VariableGaussTransform.cxx:658
 VariableGaussTransform.cxx:659
 VariableGaussTransform.cxx:660
 VariableGaussTransform.cxx:661
 VariableGaussTransform.cxx:662
 VariableGaussTransform.cxx:663
 VariableGaussTransform.cxx:664
 VariableGaussTransform.cxx:665
 VariableGaussTransform.cxx:666
 VariableGaussTransform.cxx:667
 VariableGaussTransform.cxx:668
 VariableGaussTransform.cxx:669
 VariableGaussTransform.cxx:670
 VariableGaussTransform.cxx:671
 VariableGaussTransform.cxx:672
 VariableGaussTransform.cxx:673
 VariableGaussTransform.cxx:674
 VariableGaussTransform.cxx:675
 VariableGaussTransform.cxx:676
 VariableGaussTransform.cxx:677
 VariableGaussTransform.cxx:678
 VariableGaussTransform.cxx:679
 VariableGaussTransform.cxx:680
 VariableGaussTransform.cxx:681
 VariableGaussTransform.cxx:682
 VariableGaussTransform.cxx:683
 VariableGaussTransform.cxx:684
 VariableGaussTransform.cxx:685
 VariableGaussTransform.cxx:686
 VariableGaussTransform.cxx:687
 VariableGaussTransform.cxx:688
 VariableGaussTransform.cxx:689
 VariableGaussTransform.cxx:690
 VariableGaussTransform.cxx:691
 VariableGaussTransform.cxx:692
 VariableGaussTransform.cxx:693
 VariableGaussTransform.cxx:694
 VariableGaussTransform.cxx:695
 VariableGaussTransform.cxx:696
 VariableGaussTransform.cxx:697
 VariableGaussTransform.cxx:698
 VariableGaussTransform.cxx:699
 VariableGaussTransform.cxx:700
 VariableGaussTransform.cxx:701
 VariableGaussTransform.cxx:702
 VariableGaussTransform.cxx:703
 VariableGaussTransform.cxx:704
 VariableGaussTransform.cxx:705
 VariableGaussTransform.cxx:706
 VariableGaussTransform.cxx:707
 VariableGaussTransform.cxx:708
 VariableGaussTransform.cxx:709
 VariableGaussTransform.cxx:710
 VariableGaussTransform.cxx:711
 VariableGaussTransform.cxx:712
 VariableGaussTransform.cxx:713
 VariableGaussTransform.cxx:714
 VariableGaussTransform.cxx:715
 VariableGaussTransform.cxx:716
 VariableGaussTransform.cxx:717
 VariableGaussTransform.cxx:718
 VariableGaussTransform.cxx:719
 VariableGaussTransform.cxx:720
 VariableGaussTransform.cxx:721
 VariableGaussTransform.cxx:722
 VariableGaussTransform.cxx:723
 VariableGaussTransform.cxx:724
 VariableGaussTransform.cxx:725
 VariableGaussTransform.cxx:726
 VariableGaussTransform.cxx:727
 VariableGaussTransform.cxx:728
 VariableGaussTransform.cxx:729
 VariableGaussTransform.cxx:730
 VariableGaussTransform.cxx:731
 VariableGaussTransform.cxx:732
 VariableGaussTransform.cxx:733
 VariableGaussTransform.cxx:734
 VariableGaussTransform.cxx:735
 VariableGaussTransform.cxx:736
 VariableGaussTransform.cxx:737
 VariableGaussTransform.cxx:738
 VariableGaussTransform.cxx:739
 VariableGaussTransform.cxx:740
 VariableGaussTransform.cxx:741
 VariableGaussTransform.cxx:742
 VariableGaussTransform.cxx:743
 VariableGaussTransform.cxx:744
 VariableGaussTransform.cxx:745
 VariableGaussTransform.cxx:746
 VariableGaussTransform.cxx:747
 VariableGaussTransform.cxx:748
 VariableGaussTransform.cxx:749
 VariableGaussTransform.cxx:750
 VariableGaussTransform.cxx:751
 VariableGaussTransform.cxx:752
 VariableGaussTransform.cxx:753
 VariableGaussTransform.cxx:754
 VariableGaussTransform.cxx:755
 VariableGaussTransform.cxx:756
 VariableGaussTransform.cxx:757
 VariableGaussTransform.cxx:758
 VariableGaussTransform.cxx:759
 VariableGaussTransform.cxx:760
 VariableGaussTransform.cxx:761
 VariableGaussTransform.cxx:762
 VariableGaussTransform.cxx:763
 VariableGaussTransform.cxx:764
 VariableGaussTransform.cxx:765
 VariableGaussTransform.cxx:766
 VariableGaussTransform.cxx:767
 VariableGaussTransform.cxx:768
 VariableGaussTransform.cxx:769
 VariableGaussTransform.cxx:770
 VariableGaussTransform.cxx:771
 VariableGaussTransform.cxx:772
 VariableGaussTransform.cxx:773
 VariableGaussTransform.cxx:774
 VariableGaussTransform.cxx:775
 VariableGaussTransform.cxx:776
 VariableGaussTransform.cxx:777
 VariableGaussTransform.cxx:778
 VariableGaussTransform.cxx:779
 VariableGaussTransform.cxx:780
 VariableGaussTransform.cxx:781
 VariableGaussTransform.cxx:782
 VariableGaussTransform.cxx:783
 VariableGaussTransform.cxx:784
 VariableGaussTransform.cxx:785
 VariableGaussTransform.cxx:786
 VariableGaussTransform.cxx:787
 VariableGaussTransform.cxx:788
 VariableGaussTransform.cxx:789
 VariableGaussTransform.cxx:790
 VariableGaussTransform.cxx:791
 VariableGaussTransform.cxx:792
 VariableGaussTransform.cxx:793
 VariableGaussTransform.cxx:794
 VariableGaussTransform.cxx:795
 VariableGaussTransform.cxx:796
 VariableGaussTransform.cxx:797
 VariableGaussTransform.cxx:798
 VariableGaussTransform.cxx:799
 VariableGaussTransform.cxx:800
 VariableGaussTransform.cxx:801
 VariableGaussTransform.cxx:802
 VariableGaussTransform.cxx:803
 VariableGaussTransform.cxx:804
 VariableGaussTransform.cxx:805
 VariableGaussTransform.cxx:806
 VariableGaussTransform.cxx:807
 VariableGaussTransform.cxx:808
 VariableGaussTransform.cxx:809
 VariableGaussTransform.cxx:810
 VariableGaussTransform.cxx:811
 VariableGaussTransform.cxx:812
 VariableGaussTransform.cxx:813
 VariableGaussTransform.cxx:814
 VariableGaussTransform.cxx:815
 VariableGaussTransform.cxx:816
 VariableGaussTransform.cxx:817
 VariableGaussTransform.cxx:818
 VariableGaussTransform.cxx:819
 VariableGaussTransform.cxx:820