

/**
 * \file ToFdEdx_patch.h
 * \authors Rita Carbone & Lucia Consiglio & Wolfgang Menn
 */
#ifndef tofdEdx_patch_h
#define tofdEdx_patch_h

#include <PamLevel2.h>

#include <TTree.h>
#include <TFriendElement.h>
#include <TChain.h>
#include <TFile.h>
#include <TList.h>
#include <TF1.h>
#include <TKey.h>
#include <TSystemFile.h>
#include <TSystemDirectory.h>
#include <TSQLServer.h>

#include <iostream>

using namespace std;


class ToF_geometry : public TObject {

private:
  TArrayI  ePlane, eXY;

public:
  ToF_geometry() {
    int plane[24] = { 
      0, 0, 0, 0, 0, 0, 0, 0,
      1, 1, 1, 1, 1, 1, 
      2, 2,             
      3, 3,             
      4, 4, 4,
      5, 5, 5
    };
    int plXY[6]= {  2,  1,  1,  2,  2,  1 }; // X==1, Y==2 */
    ePlane.Set(24,plane);
    eXY.Set(6,plXY);
  }

  int GetPad(   int idpmt)  { return (int)((idpmt+0.5)/2.); }
  int GetPlane( int idpmt)  { return ePlane[ GetPad(idpmt) ];  }
  int GetXY(    int idpmt)  { return eXY[ GetPlane(idpmt) ]; }

   ClassDef(ToF_geometry,1);

};

/**
 *
 * Class to store and calculate variables useful for nuclei analysis
 */
class ToFdEdx_patch : public TObject {         //class definition

 private:
    //
    PamLevel2  *L2;
    Int_t      eNtr;   // number of tracker tracks
    const char*  trkAlg; 

    ToF_geometry  eGeom;  // ToF geometry
    //

    UInt_t OBT;
    UInt_t PKT;
    UInt_t atime;
    Int_t tr;
    
    Float_t  adc_he;
    
//  ToF track dependent
    TArrayF eDEDXpmt;  // 0-47  pmt dEdx
    TArrayF eZpmt;     // 0-47  pmt charge
    TArrayF eDEDXpad;  // 0-23  paddle dEdx
    TArrayF eZpad;     // 0-23  paddle charge
    TArrayF eDEDXlayer;  // 0-5 layer dEdx
    TArrayF eZlayer;     // 0-5 layer charge
    TArrayF eDEDXplane;  // 0-2 plane dEdx
    TArrayF eZplane;     // 0-2 plane charge

    TArrayF INFOpmt;  // 0-47 pmt status
    TArrayF INFOlayer;  //0-5 layer status
  


//  ToF standalone
    TArrayF eDEDXpmtstd;  // 0-47  pmt dEdx
    TArrayF eZpmtstd;     // 0-47  pmt charge
    TArrayF eDEDXpadstd;  // 0-23  paddle dEdx
    TArrayF eZpadstd;     // 0-23  paddle charge
    TArrayF eDEDXlayerstd;  // 0-5 layer dEdx
    TArrayF eZlayerstd;     // 0-5 layer charge
    TArrayF INFOpmtstd;  // 0-47 pmt status
    TArrayF INFOlayerstd;  //0-5 layer status   

    // parameters:
  TArrayF PMTsat;  // 0-47  saturation parameters


    TArrayF A0_array[100];  //  48 x 100  define an array of 48 elements per each time interval
    TArrayF A1_array[100];   
    TArrayF A2_array[100];
    TArrayF A3_array[100];
    TArrayF A4_array[100];
    TArrayF A5_array[100];

    Float_t A0[48];  
    Float_t A1[48];   
    Float_t A2[48];
    Float_t A3[48];
    Float_t A4[48];
    Float_t A5[48];

    UInt_t T_int_min[100];  
    UInt_t T_int_max[100];
    UInt_t tmin_atten,tmax_atten;
    Int_t ical_atten;

    TArrayF dedx_corr_mp[3500];  // 48 x 3500  define an array of 48 elements per each time interval
    TArrayF dedx_corr_mhe[3500];  // 48 x 3500  define an array of 48 elements per each time interval
    TArrayF dedx_corr_mc[3500];  // 48 x 3500  define an array of 48 elements per each time interval

    UInt_t mtime[3500];
    Int_t ical_2nd;
    UInt_t tmin_2nd,tmax_2nd;
    

//    TArrayF TDx[48];  // 200 x 48  define an array of 200 elements per each pmt
//    TArrayF TDy[48];
//    TArrayF parAtt[48];      // 48 x 6

    TArrayF parPos[48];      // 48 x 4
    TArrayF parDesatBB[48];  // 48 x 3
    TArrayF parBBneg[48];    // 48 x 3
    TArrayF parBBpos;        // 48 x 1
    TArrayF parBBpol4[48];   // 48 x 5  for pol4 parameters

   
 public:
    ToFdEdx_patch() {Clear();}   // class constructor
    ~ToFdEdx_patch(){ Delete(); };  // class distructor
    //
    void Clear(Option_t *option="");
    void Delete(Option_t *option="") { Clear(); }

//    void InitPar(const char *pardir);  // init parameters
    void InitPar(const char *pardir, const char  *param);  // init parameters

    void Define_PMTsat();
//    void ReadParTD( Int_t ipmt, const char *fname  );

    void ReadParAtt(const char *pardir, const char *param);
//    void ReadParAtt(            const char *fname, const char *param );
    void ReadParPos(            const char *fname  );
    void ReadParBBneg(          const char *fname  );
    void ReadParBBpos(          const char *fname  );
    void ReadParDesatBB(        const char *fname  );
    void ReadParBBpol4(          const char *fname  );



//    void Process( PamLevel2 *l2p, Int_t itr=0 ); ///< Process data for track number itr
    void Process( PamLevel2 *l2p, const char* alg,  const char  *tri_or_bi ); ///< Process data 10th red 
    void Print(Option_t *option="");
    void PrintTD();

// track dependent results

    Float_t GetdEdx_pmt(Int_t ipmt) { return eDEDXpmt[ipmt]; }  // 0-47 dEdx for each PMT for tracked events
    Float_t GetCharge_pmt(Int_t ipmt) {return eZpmt[ipmt];}  // 0-47 Z for each PMT for tracked events
    Float_t GetdEdx_pad(Int_t ipad) {return eDEDXpad[ipad];}  // 0-23 dEdx for each paddle for tracked events (no request of consistency between PMT's response when both on!)
    Float_t GetCharge_pad(Int_t ipad) {return  eZpad[ipad];}  // 0-23 Z for each paddle for tracked events (no request of consistency)
    Float_t GetdEdx_layer(Int_t ilay) {return eDEDXlayer[ilay];}  // 0-5 dEdx for each layer for tracked events
    Float_t GetCharge_layer(Int_t ilay) {return eZlayer[ilay];}  // 0-5 Z for each layer for tracked events
 


// ToF standalone results
    Float_t GetdEdx_pmtstd(Int_t ipmt) { return eDEDXpmtstd[ipmt]; }  // 0-47 dEdx for each PMT for tracked events
    Float_t GetCharge_pmtstd(Int_t ipmt) {return eZpmtstd[ipmt];}  // 0-47 Z for each PMT for tracked events
    Float_t GetdEdx_padstd(Int_t ipad) {return eDEDXpadstd[ipad];}  // 0-23 dEdx for each paddle for tracked events (no request of consistency between PMT's response when both on!)
    Float_t GetCharge_padstd(Int_t ipad) {return  eZpadstd[ipad];}  // 0-23 Z for each paddle for tracked events (no request of consistency)
    Float_t GetdEdx_layerstd(Int_t ilay) {return eDEDXlayerstd[ilay];}  // 0-5 dEdx for each layer for tracked events
    Float_t GetCharge_layerstd(Int_t ilay) {return eZlayerstd[ilay];}  // 0-5 Z for each layer for tracked events
 

    
    Float_t GetInfo_pmt(Int_t ipmt) {return INFOpmt[ipmt];} // 0-47 pmt status  

    /* INFOpmt table:
       
       INFOpmt[ii]=0  --->  everithing is ok!
       INFOpmt[ii]=1  --->  beta not good (<0.05 || >2)
       INFOpmt[ii]=2  --->  PMT OFF
       INFOpmt[ii]=3  --->  PMT saturated
       INFOpmt[ii]=4  --->  error during the correction for the incidence angle
       INFOpmt[ii]=5  --->  error during the correction for the dependence on the position
       INFOpmt[ii]=6  --->  error in dEdx reconstruction
       INFOpmt[ii]=7  --->  error in Z reconstruction 
    */

    Float_t GetInfo_layer(Int_t ilay) {return INFOlayer[ilay];}  // 0-5 layer status

    /* INFOlayer table:
       
       INFOlayer[ii]=0  --->  everithing is ok!
       INFOlayer[ii]=1  --->  beta not good (<0.05 || >2)
       INFOlayer[ii]=2  --->  only one PMT is OFF (but you get the other one to have the measurement)
       INFOlayer[ii]=3  --->  only one PMT is saturated (but you get the other one to have the measurement)
       INFOlayer[ii]=4  --->  only one PMT with a wrong reconstruction  (but you get the other one to have the measurement)
       INFOlayer[ii]=5  --->  the 2 PMTs involved give different measurement (actually they differ for more then 1.5, to be tuned...)
       INFOlayer[ii]=6  --->  saturated layer (both PMTs)
       INFOlayer[ii]=7  --->  all PMTs show some error during reconstruction
       INFOlayer[ii]=8  --->  1 PMT is OFF and 1 is saturated (it happens quiet only on S115...)
       INFOlayer[ii]=9  --->  OFF layer
    */

 private:
    double f_adcPC( float x );
 
   double f_BB( TArrayF &p, float x );
   double f_BBpol4( TArrayF &p, float x );

   double f_BB5B( float x );
   double f_BB5Bpol4( float x );


//    double f_att( TArrayF &p, float x ) ;
    double f_att(float C0, float C1, float C2, float C3, float C4, float C5, float x ) ;
    double f_att5B( float x );
    double f_desatBB( TArrayF &p, float x );  
    double f_desatBB5B( float x );
    double f_pos( TArrayF &p, float x );
    double f_pos5B( float x );
 //   float Get_adc_he( int id, float pl_x[6], float pl_y[6]);
    float Get_adc_he( int id, float x);
   
    
    
    
    ClassDef(ToFdEdx_patch,1);
};

#endif

