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

/**********************************************************************************
 * Project: TMVA - a Root-integrated toolkit for multivariate data analysis       *
 * Package: TMVA                                                                  *
 * Class  : VariablePCATransform                                                  *
 * 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>     - U of 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)                                          *
 **********************************************************************************/

#include <iostream>
#include <iomanip>
#include <stdexcept>
#include <algorithm>

#include "TVectorF.h"
#include "TVectorD.h"
#include "TMatrixD.h"
#include "TMatrixDBase.h"

#include "TMVA/VariablePCATransform.h"

#ifndef ROOT_TMVA_MsgLogger
#include "TMVA/MsgLogger.h"
#endif
#include "TMVA/DataSet.h"
#include "TMVA/Tools.h"

ClassImp(TMVA::VariablePCATransform)

//_______________________________________________________________________
TMVA::VariablePCATransform::VariablePCATransform( DataSetInfo& dsi )
: VariableTransformBase( dsi, Types::kPCA, "PCA" )
{
   // constructor
}

//_______________________________________________________________________
TMVA::VariablePCATransform::~VariablePCATransform()
{
   // destructor
   for (UInt_t i=0; i<fMeanValues.size(); i++) {
      if (fMeanValues.at(i)   != 0) delete fMeanValues.at(i);
      if (fEigenVectors.at(i) != 0) delete fEigenVectors.at(i);
   }
}

//_______________________________________________________________________
void TMVA::VariablePCATransform::Initialize()
{
   // initialization of the transformation.
   // Has to be called in the preparation and not in the constructor,
   // since the number of classes it not known at construction, but
   // only after the creation of the DataSet which might be later.
}

//_______________________________________________________________________
Bool_t TMVA::VariablePCATransform::PrepareTransformation (const std::vector<Event*>& events)
{
   // calculate the principal components using the ROOT class TPrincipal
   // and the normalization
   Initialize();

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

   Log() << kINFO << "Preparing the Principle Component (PCA) transformation..." << Endl;

   UInt_t inputSize = fGet.size();

   SetNVariables(inputSize);

   // TPrincipal doesn't support PCA transformation for 1 or less variables
   if (inputSize <= 1) {
      Log() << kFATAL << "Cannot perform PCA transformation for " << inputSize << " variable only" << Endl;
      return kFALSE;
   }

   if (inputSize > 200) { 
      Log() << kINFO << "----------------------------------------------------------------------------"
            << Endl;
      Log() << kINFO
            << ": More than 200 variables, will not calculate PCA!" << Endl;
      Log() << kINFO << "----------------------------------------------------------------------------"
            << Endl;
      return kFALSE;
   }

   CalculatePrincipalComponents( events );

   SetCreated( kTRUE );

   return kTRUE;
}

//_______________________________________________________________________
const TMVA::Event* TMVA::VariablePCATransform::Transform( const Event* const ev, Int_t cls ) const
{
   // apply the principal component analysis
   if (!IsCreated()) return 0;

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

   // if we have more than one class, take the last PCA analysis where all classes are combined if
   // the cls parameter is outside the defined classes
   // If there is only one class, then no extra class for all events of all classes has to be created

   //if (cls < 0 || cls > GetNClasses()) cls = (fMeanValues.size()==1?0:2);//( GetNClasses() == 1 ? 0 : 1 );  ;
   // EVT this is a workaround to address the reader problem with transforma and EvaluateMVA(std::vector<float/double> ,...) 
   if (cls < 0 || cls >= (int) fMeanValues.size()) cls = fMeanValues.size()-1;
   // EVT workaround end

   // Perform PCA and put it into PCAed events tree

   if (fTransformedEvent==0 ) {
      fTransformedEvent = new Event();
   }

   std::vector<Float_t> input;
   std::vector<Char_t>  mask;
   std::vector<Float_t> principalComponents;

   Bool_t hasMaskedEntries = GetInput( ev, input, mask );

   if( hasMaskedEntries ){ // targets might be masked (for events where the targets have not been computed yet)
      UInt_t numMasked = std::count(mask.begin(), mask.end(), (Char_t)kTRUE);
      UInt_t numOK     = std::count(mask.begin(), mask.end(), (Char_t)kFALSE);
      if( numMasked>0 && numOK>0 ){
	 Log() << kFATAL << "You mixed variables and targets in the decorrelation transformation. This is not possible." << Endl;
      }
      SetOutput( fTransformedEvent, input, mask, ev );
      return fTransformedEvent;
   }

   X2P( principalComponents, input, cls );
   SetOutput( fTransformedEvent, principalComponents, mask, ev );

   return fTransformedEvent;
}

//_______________________________________________________________________
const TMVA::Event* TMVA::VariablePCATransform::InverseTransform( const Event* const ev, Int_t cls ) const
{
   // apply the principal component analysis
   // TODO: implementation of inverse transformation
//    Log() << kFATAL << "Inverse transformation for PCA transformation not yet implemented. Hence, this transformation cannot be applied together with regression. Please contact the authors if necessary." << Endl;

   if (!IsCreated()) return 0;
//   const Int_t inputSize = fGet.size();
   const UInt_t nCls = GetNClasses();
   //UInt_t evCls = ev->GetClass();

   // if we have more than one class, take the last PCA analysis where all classes are combined if
   // the cls parameter is outside the defined classes
   // If there is only one class, then no extra class for all events of all classes has to be created
   if (cls < 0 || UInt_t(cls) > nCls) cls = (fMeanValues.size()==1?0:2);//( GetNClasses() == 1 ? 0 : 1 );  ;
   // Perform PCA and put it into PCAed events tree

   if (fBackTransformedEvent==0 ) fBackTransformedEvent = new Event();

   std::vector<Float_t> principalComponents;
   std::vector<Char_t>  mask;
   std::vector<Float_t> output;

   GetInput( ev, principalComponents, mask, kTRUE );
   P2X( output, principalComponents, cls );
   SetOutput( fBackTransformedEvent, output, mask, ev, kTRUE );

   return fBackTransformedEvent;
}

//_______________________________________________________________________
void TMVA::VariablePCATransform::CalculatePrincipalComponents( const std::vector< Event*>& events )
{
   // calculate the principal components for the signal and the background data
   // it uses the MakePrincipal method of ROOT's TPrincipal class

   UInt_t nvars = 0, ntgts = 0, nspcts = 0;
   CountVariableTypes( nvars, ntgts, nspcts );
   if( nvars>0  && ntgts>0 )
      Log() << kFATAL << "Variables and targets cannot be mixed in PCA transformation." << Endl;

   const Int_t inputSize = fGet.size();

   // if we have more than one class, add another PCA analysis which combines all classes
   const UInt_t nCls = GetNClasses();
   const UInt_t maxPCA = (nCls<=1) ? nCls : nCls+1;

   // PCA [signal/background/class x/class y/... /all classes]
   std::vector<TPrincipal*> pca(maxPCA);
   for (UInt_t i=0; i<maxPCA; i++) pca[i] = new TPrincipal(nvars,"");

   // !! Not normalizing and not storing input data, for performance reasons. Should perhaps restore normalization.
   // But this can be done afterwards by adding a normalisation transformation (user defined)

   Long64_t ievt, entries = events.size();
   Double_t *dvec = new Double_t[inputSize];

   std::vector<Float_t> input;
   std::vector<Char_t>  mask;
   for (ievt=0; ievt<entries; ievt++) {
      const Event* ev = events[ievt];
      UInt_t cls = ev->GetClass();

      Bool_t hasMaskedEntries = GetInput( ev, input, mask );
      if (hasMaskedEntries){
	 Log() << kWARNING << "Print event which triggers an error" << Endl;
	 ev->Print(Log());
	 Log() << kFATAL << "Masked entries found in event read in when calculating the principal components for the PCA transformation." << Endl;
      }

      UInt_t iinp = 0;
      for( std::vector<Float_t>::iterator itInp = input.begin(), itInpEnd = input.end(); itInp != itInpEnd; ++itInp )
      {
	 Float_t value = (*itInp);
	 dvec[iinp] = (Double_t)value;
	 ++iinp;
      }

      pca.at(cls)->AddRow( dvec );
      if (nCls > 1) pca.at(maxPCA-1)->AddRow( dvec );
   }

   // delete possible leftovers
   for (UInt_t i=0; i<fMeanValues.size(); i++)   if (fMeanValues[i]   != 0) delete fMeanValues[i];
   for (UInt_t i=0; i<fEigenVectors.size(); i++) if (fEigenVectors[i] != 0) delete fEigenVectors[i];
   fMeanValues.resize(maxPCA,0);
   fEigenVectors.resize(maxPCA,0);

   for (UInt_t i=0; i<maxPCA; i++ ) {
      pca.at(i)->MakePrincipals();

      // retrieve mean values, eigenvectors and sigmas
      fMeanValues[i]   = new TVectorD( *(pca.at(i)->GetMeanValues()) ); // need to copy since we want to own
      fEigenVectors[i] = new TMatrixD( *(pca.at(i)->GetEigenVectors()) );
   }

   for (UInt_t i=0; i<maxPCA; i++) delete pca.at(i);
   delete [] dvec;
}

//_______________________________________________________________________
void TMVA::VariablePCATransform::X2P( std::vector<Float_t>& pc, const std::vector<Float_t>& x, Int_t cls ) const
{
   // Calculate the principal components from the original data vector
   // x, and return it in p (function extracted from TPrincipal::X2P)
   // It's the users responsibility to make sure that both x and p are
   // of the right size (i.e., memory must be allocated for p)
   const Int_t nInput = x.size();
   pc.assign(nInput,0);

   for (Int_t i = 0; i < nInput; i++) {
      Double_t pv = 0;
      for (Int_t j = 0; j < nInput; j++)
         pv += (((Double_t)x.at(j)) - (*fMeanValues.at(cls))(j)) * (*fEigenVectors.at(cls))(j,i);
      pc[i] = pv;
   }
}

//_______________________________________________________________________
void TMVA::VariablePCATransform::P2X( std::vector<Float_t>& x, const std::vector<Float_t>& pc, Int_t cls ) const
{
   // Perform the back-transformation from the principal components
   // pc, and return x 
   // It's the users responsibility to make sure that both x and pc are
   // of the right size (i.e., memory must be allocated for p)
   const Int_t nInput = pc.size();
   x.assign(nInput,0);

   for (Int_t i = 0; i < nInput; i++) {
      Double_t xv = 0;
      for (Int_t j = 0; j < nInput; j++)
         xv += (((Double_t)pc.at(j)) * (*fEigenVectors.at(cls))(i,j) ) + (*fMeanValues.at(cls))(j);
      x[i] = xv;
   }
}

//_______________________________________________________________________
void TMVA::VariablePCATransform::WriteTransformationToStream( std::ostream& o ) const
{
   // write mean values to stream
   for (Int_t sbType=0; sbType<2; sbType++) {
      o << "# PCA mean values " << std::endl;
      const TVectorD* means = fMeanValues[sbType];
      o << (sbType==0 ? "Signal" : "Background") << " " << means->GetNrows() << std::endl;
      for (Int_t row = 0; row<means->GetNrows(); row++) {
         o << std::setprecision(12) << std::setw(20) << (*means)[row];
      }
      o << std::endl;
   }
   o << "##" << std::endl;

   // write eigenvectors to stream
   for (Int_t sbType=0; sbType<2; sbType++) {
      o << "# PCA eigenvectors " << std::endl;
      const TMatrixD* mat = fEigenVectors[sbType];
      o << (sbType==0 ? "Signal" : "Background") << " " << mat->GetNrows() << " x " << mat->GetNcols() << std::endl;
      for (Int_t row = 0; row<mat->GetNrows(); row++) {
         for (Int_t col = 0; col<mat->GetNcols(); col++) {
            o << std::setprecision(12) << std::setw(20) << (*mat)[row][col] << " ";
         }
         o << std::endl;
      }
   }
   o << "##" << std::endl;
}

//_______________________________________________________________________
void TMVA::VariablePCATransform::AttachXMLTo(void* parent) {
   // create XML description of PCA transformation

   void* trfxml = gTools().AddChild(parent, "Transform");
   gTools().AddAttr(trfxml, "Name", "PCA");

   VariableTransformBase::AttachXMLTo( trfxml );

   // write mean values to stream
   for (UInt_t sbType=0; sbType<fMeanValues.size(); sbType++) {
      void* meanxml = gTools().AddChild( trfxml, "Statistics");
      const TVectorD* means = fMeanValues[sbType];
      gTools().AddAttr( meanxml, "Class",     (sbType==0 ? "Signal" :(sbType==1 ? "Background":"Combined")) );
      gTools().AddAttr( meanxml, "ClassIndex", sbType );
      gTools().AddAttr( meanxml, "NRows",      means->GetNrows() );
      TString meansdef = "";
      for (Int_t row = 0; row<means->GetNrows(); row++)
         meansdef += gTools().StringFromDouble((*means)[row]) + " ";
      gTools().AddRawLine( meanxml, meansdef );
   }

   // write eigenvectors to stream
   for (UInt_t sbType=0; sbType<fEigenVectors.size(); sbType++) {
      void* evxml = gTools().AddChild( trfxml, "Eigenvectors");
      const TMatrixD* mat = fEigenVectors[sbType];
      gTools().AddAttr( evxml, "Class",      (sbType==0 ? "Signal" :(sbType==1 ? "Background":"Combined") ) );
      gTools().AddAttr( evxml, "ClassIndex", sbType );
      gTools().AddAttr( evxml, "NRows",      mat->GetNrows() );
      gTools().AddAttr( evxml, "NCols",      mat->GetNcols() );
      TString evdef = "";
      for (Int_t row = 0; row<mat->GetNrows(); row++)
         for (Int_t col = 0; col<mat->GetNcols(); col++)
            evdef += gTools().StringFromDouble((*mat)[row][col]) + " ";
      gTools().AddRawLine( evxml, evdef );
   }
}

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

   Int_t nrows, ncols;
   UInt_t clsIdx;
   TString classtype;
   TString nodeName;

   Bool_t newFormat = kFALSE;

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

   if( newFormat ){
      // ------------- new format --------------------
      // read input
      VariableTransformBase::ReadFromXML( inpnode );

   }

   void* ch = gTools().GetChild(trfnode);
   while (ch) {
      nodeName = gTools().GetName(ch);
      if (nodeName == "Statistics") {
         // read mean values
         gTools().ReadAttr(ch, "Class",      classtype);
         gTools().ReadAttr(ch, "ClassIndex", clsIdx);
         gTools().ReadAttr(ch, "NRows",      nrows);

         // set the correct size
         if (fMeanValues.size()<=clsIdx) fMeanValues.resize(clsIdx+1,0);
         if (fMeanValues[clsIdx]==0) fMeanValues[clsIdx] = new TVectorD( nrows );
         fMeanValues[clsIdx]->ResizeTo( nrows );

         // now read vector entries
         std::stringstream s(gTools().GetContent(ch));
         for (Int_t row = 0; row<nrows; row++) s >> (*fMeanValues[clsIdx])(row);
      }
      else if ( nodeName == "Eigenvectors" ) {
         // Read eigenvectors
         gTools().ReadAttr(ch, "Class",      classtype);
         gTools().ReadAttr(ch, "ClassIndex", clsIdx);
         gTools().ReadAttr(ch, "NRows",      nrows);
         gTools().ReadAttr(ch, "NCols",      ncols);

         if (fEigenVectors.size()<=clsIdx) fEigenVectors.resize(clsIdx+1,0);
         if (fEigenVectors[clsIdx]==0) fEigenVectors[clsIdx] = new TMatrixD( nrows, ncols );
         fEigenVectors[clsIdx]->ResizeTo( nrows, ncols );

         // now read matrix entries
         std::stringstream s(gTools().GetContent(ch));
         for (Int_t row = 0; row<nrows; row++)
            for (Int_t col = 0; col<ncols; col++)
               s >> (*fEigenVectors[clsIdx])[row][col];
      } // done reading eigenvectors
      ch = gTools().GetNextChild(ch);
   }

   SetCreated();
}

//_______________________________________________________________________
void TMVA::VariablePCATransform::ReadTransformationFromStream( std::istream& istr, const TString& classname )
{
   // Read mean values from input stream
   char buf[512];
   istr.getline(buf,512);
   TString strvar, dummy;
   Int_t nrows(0), ncols(0);
   UInt_t classIdx=(classname=="signal"?0:1);

   for (UInt_t i=0; i<fMeanValues.size(); i++) {
      if (fMeanValues.at(i)   != 0) delete fMeanValues.at(i);
      if (fEigenVectors.at(i) != 0) delete fEigenVectors.at(i);
   }
   fMeanValues.resize(3);
   fEigenVectors.resize(3);

   Log() << kINFO << "VariablePCATransform::ReadTransformationFromStream(): " << Endl;

   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=="signal" || strvar=="background") {

         sstr >> nrows;
         Int_t sbType = (strvar=="signal" ? 0 : 1);

         if (fMeanValues[sbType] == 0) fMeanValues[sbType] = new TVectorD( nrows );
         else                          fMeanValues[sbType]->ResizeTo( nrows );

         // now read vector entries
         for (Int_t row = 0; row<nrows; row++) istr >> (*fMeanValues[sbType])(row);

      } // done reading vector

      istr.getline(buf,512); // reading the next line
   }

   // Read eigenvectors from input stream
   istr.getline(buf,512);
   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=="signal" || strvar=="background") {

         // coverity[tainted_data_argument]
         sstr >> nrows >> dummy >> ncols;
         Int_t sbType = (strvar=="signal" ? 0 : 1);

         if (fEigenVectors[sbType] == 0) fEigenVectors[sbType] = new TMatrixD( nrows, ncols );
         else                            fEigenVectors[sbType]->ResizeTo( nrows, ncols );

         // now read matrix entries
         for (Int_t row = 0; row<fEigenVectors[sbType]->GetNrows(); row++) {
            for (Int_t col = 0; col<fEigenVectors[sbType]->GetNcols(); col++) {
               istr >> (*fEigenVectors[sbType])[row][col];
            }
         }

      } // done reading matrix
      istr.getline(buf,512); // reading the next line
   }
   fMeanValues[2] = new TVectorD( *fMeanValues[classIdx] );
   fEigenVectors[2] = new TMatrixD( *fEigenVectors[classIdx] );

   SetCreated();
}

//_______________________________________________________________________
void TMVA::VariablePCATransform::MakeFunction( std::ostream& fout, const TString& fcncName,
                                               Int_t part, UInt_t trCounter, Int_t )
{
   // creates C++ code fragment of the PCA transform for inclusion in standalone C++ class

   UInt_t nvar = fEigenVectors[0]->GetNrows();

   // creates a PCA transformation function
   UInt_t numC = fMeanValues.size();
   if (part==1) {
      fout << std::endl;
      fout << "   void X2P_"<<trCounter<<"( const double*, double*, int ) const;" << std::endl;
      fout << "   double fMeanValues_"<<trCounter<<"["<<numC<<"]["
           << fMeanValues[0]->GetNrows()   << "];" << std::endl;   // mean values
      fout << "   double fEigenVectors_"<<trCounter<<"["<<numC<<"]["
           << fEigenVectors[0]->GetNrows() << "]["
           << fEigenVectors[0]->GetNcols() <<"];" << std::endl;   // eigenvectors
      fout << std::endl;
   }

   // sanity check
   if (numC>1){
      if (fMeanValues[0]->GetNrows()   != fMeanValues[1]->GetNrows() ||
          fEigenVectors[0]->GetNrows() != fEigenVectors[1]->GetNrows() ||
          fEigenVectors[0]->GetNcols() != fEigenVectors[1]->GetNcols()) {
         Log() << kFATAL << "<MakeFunction> Mismatch in vector/matrix dimensions" << Endl;
      }
   }

   if (part==2) {

      fout << std::endl;
      fout << "//_______________________________________________________________________" << std::endl;
      fout << "inline void " << fcncName << "::X2P_"<<trCounter<<"( const double* x, double* p, int index ) const" << std::endl;
      fout << "{" << std::endl;
      fout << "   // Calculate the principal components from the original data vector" << std::endl;
      fout << "   // x, and return it in p (function extracted from TPrincipal::X2P)" << std::endl;
      fout << "   // It's the users responsibility to make sure that both x and p are" << std::endl;
      fout << "   // of the right size (i.e., memory must be allocated for p)." << std::endl;
      fout << "   const int nVar = " << nvar << ";" << std::endl;
      fout << std::endl;
      fout << "   for (int i = 0; i < nVar; i++) {" << std::endl;
      fout << "      p[i] = 0;" << std::endl;
      fout << "      for (int j = 0; j < nVar; j++) p[i] += (x[j] - fMeanValues_"<<trCounter<<"[index][j]) * fEigenVectors_"<<trCounter<<"[index][j][i];" << std::endl;
      fout << "   }" << std::endl;
      fout << "}" << std::endl;
      fout << std::endl;
      fout << "//_______________________________________________________________________" << std::endl;
      fout << "inline void " << fcncName << "::InitTransform_"<<trCounter<<"()" << std::endl;
      fout << "{" << std::endl;
      fout << "   // PCA transformation, initialisation" << std::endl;

      // fill vector of mean values
      fout << "   // initialise vector of mean values" << std::endl;
      std::streamsize dp = fout.precision();
      for (UInt_t index=0; index<numC; index++) {
         for (int i=0; i<fMeanValues[index]->GetNrows(); i++) {
            fout << "   fMeanValues_"<<trCounter<<"["<<index<<"]["<<i<<"] = " << std::setprecision(12)
                 << (*fMeanValues[index])(i) << ";" << std::endl;
         }
      }

      // fill matrix of eigenvectors
      fout << std::endl;
      fout << "   // initialise matrix of eigenvectors" << std::endl;
      for (UInt_t index=0; index<numC; index++) {
         for (int i=0; i<fEigenVectors[index]->GetNrows(); i++) {
            for (int j=0; j<fEigenVectors[index]->GetNcols(); j++) {
               fout << "   fEigenVectors_"<<trCounter<<"["<<index<<"]["<<i<<"]["<<j<<"] = " << std::setprecision(12)
                    << (*fEigenVectors[index])(i,j) << ";" << std::endl;
            }
         }
      }
      fout << std::setprecision(dp);
      fout << "}" << std::endl;
      fout << std::endl;
      fout << "//_______________________________________________________________________" << std::endl;
      fout << "inline void " << fcncName << "::Transform_"<<trCounter<<"( std::vector<double>& iv, int cls ) const" << std::endl;
      fout << "{" << std::endl;
      fout << "   // PCA transformation" << std::endl;
      fout << "   const int nVar = " << nvar << ";" << std::endl;
      fout << "   double *dv = new double[nVar];" << std::endl;
      fout << "   double *rv = new double[nVar];" << std::endl;
      fout << "   if (cls < 0 || cls > "<<GetNClasses()<<") {"<< std::endl;
      fout << "       if ("<<GetNClasses()<<" > 1 ) cls = "<<GetNClasses()<<";"<< std::endl;
      fout << "       else cls = "<<(numC==1?0:2)<<";"<< std::endl;
      fout << "   }"<< std::endl;

      VariableTransformBase::MakeFunction(fout, fcncName, 0, trCounter, 0 );

      fout << "   for (int ivar=0; ivar<nVar; ivar++) dv[ivar] = iv[indicesGet.at(ivar)];" << std::endl;

      fout << std::endl;
      fout << "   // Perform PCA and put it into PCAed events tree" << std::endl;
      fout << "   this->X2P_"<<trCounter<<"( dv, rv, cls );" << std::endl;
      fout << "   for (int ivar=0; ivar<nVar; ivar++) iv[indicesPut.at(ivar)] = rv[ivar];" << std::endl;

      fout << std::endl;
      fout << "   delete [] dv;" << std::endl;
      fout << "   delete [] rv;" << std::endl;
      fout << "}" << std::endl;
   }
}
 VariablePCATransform.cxx:1
 VariablePCATransform.cxx:2
 VariablePCATransform.cxx:3
 VariablePCATransform.cxx:4
 VariablePCATransform.cxx:5
 VariablePCATransform.cxx:6
 VariablePCATransform.cxx:7
 VariablePCATransform.cxx:8
 VariablePCATransform.cxx:9
 VariablePCATransform.cxx:10
 VariablePCATransform.cxx:11
 VariablePCATransform.cxx:12
 VariablePCATransform.cxx:13
 VariablePCATransform.cxx:14
 VariablePCATransform.cxx:15
 VariablePCATransform.cxx:16
 VariablePCATransform.cxx:17
 VariablePCATransform.cxx:18
 VariablePCATransform.cxx:19
 VariablePCATransform.cxx:20
 VariablePCATransform.cxx:21
 VariablePCATransform.cxx:22
 VariablePCATransform.cxx:23
 VariablePCATransform.cxx:24
 VariablePCATransform.cxx:25
 VariablePCATransform.cxx:26
 VariablePCATransform.cxx:27
 VariablePCATransform.cxx:28
 VariablePCATransform.cxx:29
 VariablePCATransform.cxx:30
 VariablePCATransform.cxx:31
 VariablePCATransform.cxx:32
 VariablePCATransform.cxx:33
 VariablePCATransform.cxx:34
 VariablePCATransform.cxx:35
 VariablePCATransform.cxx:36
 VariablePCATransform.cxx:37
 VariablePCATransform.cxx:38
 VariablePCATransform.cxx:39
 VariablePCATransform.cxx:40
 VariablePCATransform.cxx:41
 VariablePCATransform.cxx:42
 VariablePCATransform.cxx:43
 VariablePCATransform.cxx:44
 VariablePCATransform.cxx:45
 VariablePCATransform.cxx:46
 VariablePCATransform.cxx:47
 VariablePCATransform.cxx:48
 VariablePCATransform.cxx:49
 VariablePCATransform.cxx:50
 VariablePCATransform.cxx:51
 VariablePCATransform.cxx:52
 VariablePCATransform.cxx:53
 VariablePCATransform.cxx:54
 VariablePCATransform.cxx:55
 VariablePCATransform.cxx:56
 VariablePCATransform.cxx:57
 VariablePCATransform.cxx:58
 VariablePCATransform.cxx:59
 VariablePCATransform.cxx:60
 VariablePCATransform.cxx:61
 VariablePCATransform.cxx:62
 VariablePCATransform.cxx:63
 VariablePCATransform.cxx:64
 VariablePCATransform.cxx:65
 VariablePCATransform.cxx:66
 VariablePCATransform.cxx:67
 VariablePCATransform.cxx:68
 VariablePCATransform.cxx:69
 VariablePCATransform.cxx:70
 VariablePCATransform.cxx:71
 VariablePCATransform.cxx:72
 VariablePCATransform.cxx:73
 VariablePCATransform.cxx:74
 VariablePCATransform.cxx:75
 VariablePCATransform.cxx:76
 VariablePCATransform.cxx:77
 VariablePCATransform.cxx:78
 VariablePCATransform.cxx:79
 VariablePCATransform.cxx:80
 VariablePCATransform.cxx:81
 VariablePCATransform.cxx:82
 VariablePCATransform.cxx:83
 VariablePCATransform.cxx:84
 VariablePCATransform.cxx:85
 VariablePCATransform.cxx:86
 VariablePCATransform.cxx:87
 VariablePCATransform.cxx:88
 VariablePCATransform.cxx:89
 VariablePCATransform.cxx:90
 VariablePCATransform.cxx:91
 VariablePCATransform.cxx:92
 VariablePCATransform.cxx:93
 VariablePCATransform.cxx:94
 VariablePCATransform.cxx:95
 VariablePCATransform.cxx:96
 VariablePCATransform.cxx:97
 VariablePCATransform.cxx:98
 VariablePCATransform.cxx:99
 VariablePCATransform.cxx:100
 VariablePCATransform.cxx:101
 VariablePCATransform.cxx:102
 VariablePCATransform.cxx:103
 VariablePCATransform.cxx:104
 VariablePCATransform.cxx:105
 VariablePCATransform.cxx:106
 VariablePCATransform.cxx:107
 VariablePCATransform.cxx:108
 VariablePCATransform.cxx:109
 VariablePCATransform.cxx:110
 VariablePCATransform.cxx:111
 VariablePCATransform.cxx:112
 VariablePCATransform.cxx:113
 VariablePCATransform.cxx:114
 VariablePCATransform.cxx:115
 VariablePCATransform.cxx:116
 VariablePCATransform.cxx:117
 VariablePCATransform.cxx:118
 VariablePCATransform.cxx:119
 VariablePCATransform.cxx:120
 VariablePCATransform.cxx:121
 VariablePCATransform.cxx:122
 VariablePCATransform.cxx:123
 VariablePCATransform.cxx:124
 VariablePCATransform.cxx:125
 VariablePCATransform.cxx:126
 VariablePCATransform.cxx:127
 VariablePCATransform.cxx:128
 VariablePCATransform.cxx:129
 VariablePCATransform.cxx:130
 VariablePCATransform.cxx:131
 VariablePCATransform.cxx:132
 VariablePCATransform.cxx:133
 VariablePCATransform.cxx:134
 VariablePCATransform.cxx:135
 VariablePCATransform.cxx:136
 VariablePCATransform.cxx:137
 VariablePCATransform.cxx:138
 VariablePCATransform.cxx:139
 VariablePCATransform.cxx:140
 VariablePCATransform.cxx:141
 VariablePCATransform.cxx:142
 VariablePCATransform.cxx:143
 VariablePCATransform.cxx:144
 VariablePCATransform.cxx:145
 VariablePCATransform.cxx:146
 VariablePCATransform.cxx:147
 VariablePCATransform.cxx:148
 VariablePCATransform.cxx:149
 VariablePCATransform.cxx:150
 VariablePCATransform.cxx:151
 VariablePCATransform.cxx:152
 VariablePCATransform.cxx:153
 VariablePCATransform.cxx:154
 VariablePCATransform.cxx:155
 VariablePCATransform.cxx:156
 VariablePCATransform.cxx:157
 VariablePCATransform.cxx:158
 VariablePCATransform.cxx:159
 VariablePCATransform.cxx:160
 VariablePCATransform.cxx:161
 VariablePCATransform.cxx:162
 VariablePCATransform.cxx:163
 VariablePCATransform.cxx:164
 VariablePCATransform.cxx:165
 VariablePCATransform.cxx:166
 VariablePCATransform.cxx:167
 VariablePCATransform.cxx:168
 VariablePCATransform.cxx:169
 VariablePCATransform.cxx:170
 VariablePCATransform.cxx:171
 VariablePCATransform.cxx:172
 VariablePCATransform.cxx:173
 VariablePCATransform.cxx:174
 VariablePCATransform.cxx:175
 VariablePCATransform.cxx:176
 VariablePCATransform.cxx:177
 VariablePCATransform.cxx:178
 VariablePCATransform.cxx:179
 VariablePCATransform.cxx:180
 VariablePCATransform.cxx:181
 VariablePCATransform.cxx:182
 VariablePCATransform.cxx:183
 VariablePCATransform.cxx:184
 VariablePCATransform.cxx:185
 VariablePCATransform.cxx:186
 VariablePCATransform.cxx:187
 VariablePCATransform.cxx:188
 VariablePCATransform.cxx:189
 VariablePCATransform.cxx:190
 VariablePCATransform.cxx:191
 VariablePCATransform.cxx:192
 VariablePCATransform.cxx:193
 VariablePCATransform.cxx:194
 VariablePCATransform.cxx:195
 VariablePCATransform.cxx:196
 VariablePCATransform.cxx:197
 VariablePCATransform.cxx:198
 VariablePCATransform.cxx:199
 VariablePCATransform.cxx:200
 VariablePCATransform.cxx:201
 VariablePCATransform.cxx:202
 VariablePCATransform.cxx:203
 VariablePCATransform.cxx:204
 VariablePCATransform.cxx:205
 VariablePCATransform.cxx:206
 VariablePCATransform.cxx:207
 VariablePCATransform.cxx:208
 VariablePCATransform.cxx:209
 VariablePCATransform.cxx:210
 VariablePCATransform.cxx:211
 VariablePCATransform.cxx:212
 VariablePCATransform.cxx:213
 VariablePCATransform.cxx:214
 VariablePCATransform.cxx:215
 VariablePCATransform.cxx:216
 VariablePCATransform.cxx:217
 VariablePCATransform.cxx:218
 VariablePCATransform.cxx:219
 VariablePCATransform.cxx:220
 VariablePCATransform.cxx:221
 VariablePCATransform.cxx:222
 VariablePCATransform.cxx:223
 VariablePCATransform.cxx:224
 VariablePCATransform.cxx:225
 VariablePCATransform.cxx:226
 VariablePCATransform.cxx:227
 VariablePCATransform.cxx:228
 VariablePCATransform.cxx:229
 VariablePCATransform.cxx:230
 VariablePCATransform.cxx:231
 VariablePCATransform.cxx:232
 VariablePCATransform.cxx:233
 VariablePCATransform.cxx:234
 VariablePCATransform.cxx:235
 VariablePCATransform.cxx:236
 VariablePCATransform.cxx:237
 VariablePCATransform.cxx:238
 VariablePCATransform.cxx:239
 VariablePCATransform.cxx:240
 VariablePCATransform.cxx:241
 VariablePCATransform.cxx:242
 VariablePCATransform.cxx:243
 VariablePCATransform.cxx:244
 VariablePCATransform.cxx:245
 VariablePCATransform.cxx:246
 VariablePCATransform.cxx:247
 VariablePCATransform.cxx:248
 VariablePCATransform.cxx:249
 VariablePCATransform.cxx:250
 VariablePCATransform.cxx:251
 VariablePCATransform.cxx:252
 VariablePCATransform.cxx:253
 VariablePCATransform.cxx:254
 VariablePCATransform.cxx:255
 VariablePCATransform.cxx:256
 VariablePCATransform.cxx:257
 VariablePCATransform.cxx:258
 VariablePCATransform.cxx:259
 VariablePCATransform.cxx:260
 VariablePCATransform.cxx:261
 VariablePCATransform.cxx:262
 VariablePCATransform.cxx:263
 VariablePCATransform.cxx:264
 VariablePCATransform.cxx:265
 VariablePCATransform.cxx:266
 VariablePCATransform.cxx:267
 VariablePCATransform.cxx:268
 VariablePCATransform.cxx:269
 VariablePCATransform.cxx:270
 VariablePCATransform.cxx:271
 VariablePCATransform.cxx:272
 VariablePCATransform.cxx:273
 VariablePCATransform.cxx:274
 VariablePCATransform.cxx:275
 VariablePCATransform.cxx:276
 VariablePCATransform.cxx:277
 VariablePCATransform.cxx:278
 VariablePCATransform.cxx:279
 VariablePCATransform.cxx:280
 VariablePCATransform.cxx:281
 VariablePCATransform.cxx:282
 VariablePCATransform.cxx:283
 VariablePCATransform.cxx:284
 VariablePCATransform.cxx:285
 VariablePCATransform.cxx:286
 VariablePCATransform.cxx:287
 VariablePCATransform.cxx:288
 VariablePCATransform.cxx:289
 VariablePCATransform.cxx:290
 VariablePCATransform.cxx:291
 VariablePCATransform.cxx:292
 VariablePCATransform.cxx:293
 VariablePCATransform.cxx:294
 VariablePCATransform.cxx:295
 VariablePCATransform.cxx:296
 VariablePCATransform.cxx:297
 VariablePCATransform.cxx:298
 VariablePCATransform.cxx:299
 VariablePCATransform.cxx:300
 VariablePCATransform.cxx:301
 VariablePCATransform.cxx:302
 VariablePCATransform.cxx:303
 VariablePCATransform.cxx:304
 VariablePCATransform.cxx:305
 VariablePCATransform.cxx:306
 VariablePCATransform.cxx:307
 VariablePCATransform.cxx:308
 VariablePCATransform.cxx:309
 VariablePCATransform.cxx:310
 VariablePCATransform.cxx:311
 VariablePCATransform.cxx:312
 VariablePCATransform.cxx:313
 VariablePCATransform.cxx:314
 VariablePCATransform.cxx:315
 VariablePCATransform.cxx:316
 VariablePCATransform.cxx:317
 VariablePCATransform.cxx:318
 VariablePCATransform.cxx:319
 VariablePCATransform.cxx:320
 VariablePCATransform.cxx:321
 VariablePCATransform.cxx:322
 VariablePCATransform.cxx:323
 VariablePCATransform.cxx:324
 VariablePCATransform.cxx:325
 VariablePCATransform.cxx:326
 VariablePCATransform.cxx:327
 VariablePCATransform.cxx:328
 VariablePCATransform.cxx:329
 VariablePCATransform.cxx:330
 VariablePCATransform.cxx:331
 VariablePCATransform.cxx:332
 VariablePCATransform.cxx:333
 VariablePCATransform.cxx:334
 VariablePCATransform.cxx:335
 VariablePCATransform.cxx:336
 VariablePCATransform.cxx:337
 VariablePCATransform.cxx:338
 VariablePCATransform.cxx:339
 VariablePCATransform.cxx:340
 VariablePCATransform.cxx:341
 VariablePCATransform.cxx:342
 VariablePCATransform.cxx:343
 VariablePCATransform.cxx:344
 VariablePCATransform.cxx:345
 VariablePCATransform.cxx:346
 VariablePCATransform.cxx:347
 VariablePCATransform.cxx:348
 VariablePCATransform.cxx:349
 VariablePCATransform.cxx:350
 VariablePCATransform.cxx:351
 VariablePCATransform.cxx:352
 VariablePCATransform.cxx:353
 VariablePCATransform.cxx:354
 VariablePCATransform.cxx:355
 VariablePCATransform.cxx:356
 VariablePCATransform.cxx:357
 VariablePCATransform.cxx:358
 VariablePCATransform.cxx:359
 VariablePCATransform.cxx:360
 VariablePCATransform.cxx:361
 VariablePCATransform.cxx:362
 VariablePCATransform.cxx:363
 VariablePCATransform.cxx:364
 VariablePCATransform.cxx:365
 VariablePCATransform.cxx:366
 VariablePCATransform.cxx:367
 VariablePCATransform.cxx:368
 VariablePCATransform.cxx:369
 VariablePCATransform.cxx:370
 VariablePCATransform.cxx:371
 VariablePCATransform.cxx:372
 VariablePCATransform.cxx:373
 VariablePCATransform.cxx:374
 VariablePCATransform.cxx:375
 VariablePCATransform.cxx:376
 VariablePCATransform.cxx:377
 VariablePCATransform.cxx:378
 VariablePCATransform.cxx:379
 VariablePCATransform.cxx:380
 VariablePCATransform.cxx:381
 VariablePCATransform.cxx:382
 VariablePCATransform.cxx:383
 VariablePCATransform.cxx:384
 VariablePCATransform.cxx:385
 VariablePCATransform.cxx:386
 VariablePCATransform.cxx:387
 VariablePCATransform.cxx:388
 VariablePCATransform.cxx:389
 VariablePCATransform.cxx:390
 VariablePCATransform.cxx:391
 VariablePCATransform.cxx:392
 VariablePCATransform.cxx:393
 VariablePCATransform.cxx:394
 VariablePCATransform.cxx:395
 VariablePCATransform.cxx:396
 VariablePCATransform.cxx:397
 VariablePCATransform.cxx:398
 VariablePCATransform.cxx:399
 VariablePCATransform.cxx:400
 VariablePCATransform.cxx:401
 VariablePCATransform.cxx:402
 VariablePCATransform.cxx:403
 VariablePCATransform.cxx:404
 VariablePCATransform.cxx:405
 VariablePCATransform.cxx:406
 VariablePCATransform.cxx:407
 VariablePCATransform.cxx:408
 VariablePCATransform.cxx:409
 VariablePCATransform.cxx:410
 VariablePCATransform.cxx:411
 VariablePCATransform.cxx:412
 VariablePCATransform.cxx:413
 VariablePCATransform.cxx:414
 VariablePCATransform.cxx:415
 VariablePCATransform.cxx:416
 VariablePCATransform.cxx:417
 VariablePCATransform.cxx:418
 VariablePCATransform.cxx:419
 VariablePCATransform.cxx:420
 VariablePCATransform.cxx:421
 VariablePCATransform.cxx:422
 VariablePCATransform.cxx:423
 VariablePCATransform.cxx:424
 VariablePCATransform.cxx:425
 VariablePCATransform.cxx:426
 VariablePCATransform.cxx:427
 VariablePCATransform.cxx:428
 VariablePCATransform.cxx:429
 VariablePCATransform.cxx:430
 VariablePCATransform.cxx:431
 VariablePCATransform.cxx:432
 VariablePCATransform.cxx:433
 VariablePCATransform.cxx:434
 VariablePCATransform.cxx:435
 VariablePCATransform.cxx:436
 VariablePCATransform.cxx:437
 VariablePCATransform.cxx:438
 VariablePCATransform.cxx:439
 VariablePCATransform.cxx:440
 VariablePCATransform.cxx:441
 VariablePCATransform.cxx:442
 VariablePCATransform.cxx:443
 VariablePCATransform.cxx:444
 VariablePCATransform.cxx:445
 VariablePCATransform.cxx:446
 VariablePCATransform.cxx:447
 VariablePCATransform.cxx:448
 VariablePCATransform.cxx:449
 VariablePCATransform.cxx:450
 VariablePCATransform.cxx:451
 VariablePCATransform.cxx:452
 VariablePCATransform.cxx:453
 VariablePCATransform.cxx:454
 VariablePCATransform.cxx:455
 VariablePCATransform.cxx:456
 VariablePCATransform.cxx:457
 VariablePCATransform.cxx:458
 VariablePCATransform.cxx:459
 VariablePCATransform.cxx:460
 VariablePCATransform.cxx:461
 VariablePCATransform.cxx:462
 VariablePCATransform.cxx:463
 VariablePCATransform.cxx:464
 VariablePCATransform.cxx:465
 VariablePCATransform.cxx:466
 VariablePCATransform.cxx:467
 VariablePCATransform.cxx:468
 VariablePCATransform.cxx:469
 VariablePCATransform.cxx:470
 VariablePCATransform.cxx:471
 VariablePCATransform.cxx:472
 VariablePCATransform.cxx:473
 VariablePCATransform.cxx:474
 VariablePCATransform.cxx:475
 VariablePCATransform.cxx:476
 VariablePCATransform.cxx:477
 VariablePCATransform.cxx:478
 VariablePCATransform.cxx:479
 VariablePCATransform.cxx:480
 VariablePCATransform.cxx:481
 VariablePCATransform.cxx:482
 VariablePCATransform.cxx:483
 VariablePCATransform.cxx:484
 VariablePCATransform.cxx:485
 VariablePCATransform.cxx:486
 VariablePCATransform.cxx:487
 VariablePCATransform.cxx:488
 VariablePCATransform.cxx:489
 VariablePCATransform.cxx:490
 VariablePCATransform.cxx:491
 VariablePCATransform.cxx:492
 VariablePCATransform.cxx:493
 VariablePCATransform.cxx:494
 VariablePCATransform.cxx:495
 VariablePCATransform.cxx:496
 VariablePCATransform.cxx:497
 VariablePCATransform.cxx:498
 VariablePCATransform.cxx:499
 VariablePCATransform.cxx:500
 VariablePCATransform.cxx:501
 VariablePCATransform.cxx:502
 VariablePCATransform.cxx:503
 VariablePCATransform.cxx:504
 VariablePCATransform.cxx:505
 VariablePCATransform.cxx:506
 VariablePCATransform.cxx:507
 VariablePCATransform.cxx:508
 VariablePCATransform.cxx:509
 VariablePCATransform.cxx:510
 VariablePCATransform.cxx:511
 VariablePCATransform.cxx:512
 VariablePCATransform.cxx:513
 VariablePCATransform.cxx:514
 VariablePCATransform.cxx:515
 VariablePCATransform.cxx:516
 VariablePCATransform.cxx:517
 VariablePCATransform.cxx:518
 VariablePCATransform.cxx:519
 VariablePCATransform.cxx:520
 VariablePCATransform.cxx:521
 VariablePCATransform.cxx:522
 VariablePCATransform.cxx:523
 VariablePCATransform.cxx:524
 VariablePCATransform.cxx:525
 VariablePCATransform.cxx:526
 VariablePCATransform.cxx:527
 VariablePCATransform.cxx:528
 VariablePCATransform.cxx:529
 VariablePCATransform.cxx:530
 VariablePCATransform.cxx:531
 VariablePCATransform.cxx:532
 VariablePCATransform.cxx:533
 VariablePCATransform.cxx:534
 VariablePCATransform.cxx:535
 VariablePCATransform.cxx:536
 VariablePCATransform.cxx:537
 VariablePCATransform.cxx:538
 VariablePCATransform.cxx:539
 VariablePCATransform.cxx:540
 VariablePCATransform.cxx:541
 VariablePCATransform.cxx:542
 VariablePCATransform.cxx:543
 VariablePCATransform.cxx:544
 VariablePCATransform.cxx:545
 VariablePCATransform.cxx:546
 VariablePCATransform.cxx:547
 VariablePCATransform.cxx:548
 VariablePCATransform.cxx:549
 VariablePCATransform.cxx:550
 VariablePCATransform.cxx:551
 VariablePCATransform.cxx:552
 VariablePCATransform.cxx:553
 VariablePCATransform.cxx:554
 VariablePCATransform.cxx:555
 VariablePCATransform.cxx:556
 VariablePCATransform.cxx:557
 VariablePCATransform.cxx:558
 VariablePCATransform.cxx:559
 VariablePCATransform.cxx:560
 VariablePCATransform.cxx:561
 VariablePCATransform.cxx:562
 VariablePCATransform.cxx:563
 VariablePCATransform.cxx:564
 VariablePCATransform.cxx:565
 VariablePCATransform.cxx:566
 VariablePCATransform.cxx:567
 VariablePCATransform.cxx:568
 VariablePCATransform.cxx:569
 VariablePCATransform.cxx:570
 VariablePCATransform.cxx:571
 VariablePCATransform.cxx:572
 VariablePCATransform.cxx:573
 VariablePCATransform.cxx:574
 VariablePCATransform.cxx:575
 VariablePCATransform.cxx:576
 VariablePCATransform.cxx:577
 VariablePCATransform.cxx:578
 VariablePCATransform.cxx:579
 VariablePCATransform.cxx:580
 VariablePCATransform.cxx:581
 VariablePCATransform.cxx:582
 VariablePCATransform.cxx:583
 VariablePCATransform.cxx:584
 VariablePCATransform.cxx:585
 VariablePCATransform.cxx:586
 VariablePCATransform.cxx:587
 VariablePCATransform.cxx:588
 VariablePCATransform.cxx:589
 VariablePCATransform.cxx:590
 VariablePCATransform.cxx:591
 VariablePCATransform.cxx:592
 VariablePCATransform.cxx:593
 VariablePCATransform.cxx:594
 VariablePCATransform.cxx:595
 VariablePCATransform.cxx:596
 VariablePCATransform.cxx:597
 VariablePCATransform.cxx:598
 VariablePCATransform.cxx:599
 VariablePCATransform.cxx:600
 VariablePCATransform.cxx:601
 VariablePCATransform.cxx:602
 VariablePCATransform.cxx:603
 VariablePCATransform.cxx:604
 VariablePCATransform.cxx:605
 VariablePCATransform.cxx:606
 VariablePCATransform.cxx:607
 VariablePCATransform.cxx:608
 VariablePCATransform.cxx:609
 VariablePCATransform.cxx:610
 VariablePCATransform.cxx:611
 VariablePCATransform.cxx:612
 VariablePCATransform.cxx:613
 VariablePCATransform.cxx:614