/**
 * \file CaloFranzini.h
 * \author Emiliano Mocchiutti (2007/12/03)
 */
#ifndef calofranzini_h
#define calofranzini_h

#include <iostream>

#include <TTree.h>
#include <TFriendElement.h>
#include <TChain.h>
#include <TFile.h>
#include <TList.h>
#include <TKey.h>
#include <TSystemFile.h>
#include <TSystemDirectory.h>
#include <TSQLServer.h>
#include <TMatrixD.h>
#include <TMatrixF.h>
#include <TArrayI.h>
#include <TArrayF.h>
#include <TStyle.h>
#include <TCanvas.h>
#include <TStyle.h>
#include <TH1F.h>
#include <TF1.h>
#include <TGraph.h>
#include <TDecompSVD.h>
//

#include <PamLevel2.h>

using namespace std;

/**
 *
 * Class to store and calculate variables useful for analysis with the Franzini method
 */
class CaloFranzini : public TObject {

 private:
    //
    PamLevel2 *L2;
    Bool_t debug;
    TFile *lfile;
    TFile *ffile;
    Int_t nbin;
    TArrayF *brig;
    TArrayF *brigm;
    TArrayF *qplmean[17];
    TMatrixD *hmat[17];
    TMatrixD *hfmat[17];
    TMatrixD *fqplmean[17];
    Int_t N;
    Int_t NC;
    //
    // needed to avoid reprocessing the same event over and over to obtain the variables;
    //
    UInt_t OBT;
    UInt_t PKT;
    UInt_t atime;
    Int_t sntr;
    Float_t estrip[2][22][96];
    Float_t qplane[43];
    Bool_t sel;
    Bool_t cont;
    Bool_t crig;
    //
    Bool_t usepl18x;
    //
    Int_t mask18b;
    Bool_t dofull;
    Bool_t dolong;
    Int_t degfre;
    Int_t fdegfre;
    //
    Float_t longtzeta; ///< longitudinal covariance parameter used for event selection
    Float_t fulltzeta; ///< full calorimeter covariance parameter used for event selection
    //
    Float_t negfulltzeta;
    Float_t posfulltzeta;
    Float_t minsvalue;
    Float_t maxsvalue;
    Float_t aveposvar;
    Float_t avenegvar;
    Int_t numneg;
    Int_t numpos;
    //

 public:
    //
    CaloFranzini();
    CaloFranzini(PamLevel2 *L2);
    ~CaloFranzini(){ Delete(); };
    //
    Float_t GetLongTZeta(){Process(); return longtzeta;}; ///< Returns longitudinal covariance parameter used for event selection
    Float_t GetFullTZeta(){Process(); return fulltzeta;}; ///< Returns full calorimeter covariance parameter used for event selection
    //
    Float_t GetNormLongTZeta(); ///< Returns longitudinal covariance parameter used for event selection
    Float_t GetNormFullTZeta(); ///< Returns full calorimeter covariance parameter used for event selection
    //

    Float_t GetFullPositive(){Process(); return posfulltzeta;};
    Float_t GetFullNegative(){Process(); return negfulltzeta;};
    Int_t GetFullNumPositive(){Process(); return numpos;};
    Int_t GetFullNumNegative(){Process(); return numneg;};
    Float_t GetFullMaxVar(){Process(); return maxsvalue;};
    Float_t GetFullMinVar(){Process(); return minsvalue;};
    Float_t GetFullAveragePosVar(){Process(); return aveposvar;};
    Float_t GetFullAverageNegVar(){Process(); return avenegvar;};

   //
    void Selection(){sel = true; cont = false;}; ///< Set selection mode: planes from 1 to 22-N are used, plane 18 - N is masked if "emulate18" variable is true (DEFAULT);
    void Contamination(){sel = false; cont = true;}; ///< Set contamination mode: planes from N to 22 are used.
    Int_t GetDegreeOfFreedom(){return degfre;};
    Int_t GetLongDegreeOfFreedom(){return degfre;};
    Int_t GetFullDegreeOfFreedom(){return fdegfre;};
    //
    TArrayF *LoadLongAverage(Float_t rig); 
    TMatrixD *LoadCovarianceMatrix(Float_t rig);
    //
    Float_t GetAverageAt(Int_t plane, Float_t rig);
    Float_t GetHmatrixAt(Int_t i, Int_t j, Float_t rig);
    //
    Float_t GetFullAverageAt(Int_t plane, Int_t strip, Float_t rig);
    Float_t GetFullHmatrixAt(Int_t i, Int_t j, Float_t rig);
    Float_t GetFullAverageAt(Int_t plane, Int_t strip, Float_t rig, Int_t rigbin);
    Float_t GetFullHmatrixAt(Int_t i, Int_t j, Float_t rig, Int_t rigbin);
    Float_t GetFullHmatrixAt(Int_t i, Int_t j, Float_t rig, Int_t rigbin, Int_t mtherig);
    //
    Bool_t Open(TString matrixfile);
    Bool_t Open(TString longmatrixfile,TString fullmatrixfile);
    Bool_t LoadBin();
    Bool_t LoadBin(Bool_t full);
    Bool_t LoadLong();
    Bool_t LoadFull();
    Bool_t LoadMatrices();
    Bool_t LoadFullMatrices();
    TFile *GetFile(){return lfile;};
    TFile *GetLongFile(){return lfile;};
    TFile *GetFullFile(){return ffile;};
    //
    TMatrixD *LoadFullAverage(Int_t rigbin);
    TMatrixD *LoadFullNAverage(Int_t rigbin);
    void UnLoadFullAverage(Int_t rigbin);
    void UnLoadFullNAverage(Int_t rigbin);
    TMatrixF *LoadFullMatrix(Int_t rigbin);
    //    void LoadFullMatrix(Int_t rigbin, TMatrixF *&fmatri);
    void LoadFullMatrix(Int_t rigbin, TMatrixF *fmatri);
    TMatrixF *LoadFullNMatrix(Int_t rigbin);
    void UnLoadFullMatrix(Int_t rigbin);
    void UnLoadFullNMatrix(Int_t rigbin);
    //
    Int_t ConvertStrip(Int_t mstrip);
    //
    Bool_t CreateMatrixFile(TString matrixfile);
    Bool_t UpdateMatrixFile(TString matrixfile);
    void WriteNumBin(Int_t numbin);
    void WriteRigBin(TArrayF *rigbin);
    void WriteLongMean(TArrayF *qpl, Int_t bin);
    void WriteLongMatrix(TMatrixD *matrix, Int_t bin);
    void WriteFullMatrix(TMatrixD *matrix, Int_t bin);
    void WriteFullNMatrix(TMatrixF *matrix, Int_t bin);
    void WriteFullMean(TMatrixD *matrix, Int_t bin);
    void WriteFullNMean(TMatrixD *matrix, Int_t bin);
    void WriteInvertedLongMatrix(TMatrixD matrix, Int_t bin);
    void WriteInvertedFullMatrix(TMatrixD matrix, Int_t bin);
    void CloseMatrixFile();
    //
    void CalculateLongTZeta(){ dolong=true; };
    void CalculateFullTZeta(){ dofull=true; };
    void CalculateLongTZeta(Bool_t bo){ dolong=bo; };
    void CalculateFullTZeta(Bool_t bo){ dofull=bo; };
    void SetDebug(Bool_t d){ debug=d; };
    void SetNoWpreSampler(Int_t n);
    void SetNoWcalo(Int_t n);
    void SplitInto(Int_t NoWpreSampler, Int_t NoWcalo);
    Int_t GetNoWpreSampler(){return N;}; ///< Get the number of W planes used as presampler. 
    Int_t GetNoWcalo(){return NC;}; ///< Get the number of W planes used as calorimeter.
    void DrawLongAverage(Float_t rig);
    void DrawLongAverage(Int_t bin);
    void UseCaloRig(){crig=true;};
    //
    void UsePlane18X(Bool_t use){usepl18x = use;};
    //
    //
    void Clear();
    void Clear(Option_t *option){Clear();};
    void Delete();
    void Delete(Option_t *option){Delete();};
    //
    void Process(Int_t ntrack); ///< Process data track number ntrack
    void Process(); ///< Process data 
    void Print();
    void Print(Option_t *option){Print();};
    //
    ClassDef(CaloFranzini,2);
};

#endif

