
/**
 * \file TrkCalib.cpp
 * \author Elena Vannuccini
 */
#include <TrkCalib.h>
using namespace pamela;


TrkCalib::TrkCalib(){

    calib1 = new CalibTrk1Event();

};


TrkCalib::~TrkCalib(){

    calib1->Delete();

};

/**
 * Method to get the view number of the ipkt-th stored DSP-packet.
 * The view number is extracted from the DSP-header.
 */
Int_t TrkCalib::GetView(Int_t ipkt){

    if( ipkt <0 || ipkt >=6 )return 0;
    return calib1->DSPnumber[ipkt]; 

};

Int_t TrkCalib::EvaluatePar(TString what, Int_t ipkt, Int_t ivk, Float_t* result){
    
    // vector to store mean, RMS, n.points
//    Float_t* result = new Float_t[3]; 
    *(result)   = -1.;
    *(result+1) = 0.;
    *(result+2) = 0.;

    // evaluate strip range
    Int_t from = (ivk-1)*128 ;
    Int_t to= ivk*128;
    if( ivk > 0 && ivk <= 24){
	from = (ivk-1)*128 ;
	to   = ivk*128;
    }else if( ivk==0 ){
	from = 0;
	to   = 3072;
    }else if( ivk < 0 && ivk >= -3 ){
	from = (-ivk-1)*1024;
	to   =  -ivk*1024;
    }else{
	return 0;
    }


    float mean =0;
    float rms   =0;
    int   nstrip =0;
    float *pt;

    if(       what.Contains("PED") ){
	pt = (float*)(calib1->DSPped_par);
    }else if( what.Contains("SIG") ){
	pt = (float*)(calib1->DSPsig_par);
    }else{ 
	cout << "TrkCalib::EvaluatePar() --> "<<what<<" not implemented\n";
	return 0;
    };    

    int *ptbad;
    ptbad = (int*)(calib1->DSPbad_par);

    
    for(Int_t is=from; is<to; is++){
	int bad = 1;
	if( what.Contains("-BAD") && ptbad[ipkt*3072+is] == 1 )bad = 0;
	mean   += pt[ipkt*3072+is] * bad;
	rms    += pt[ipkt*3072+is] * pt[ipkt*3072+is] * bad ;
	nstrip += bad;
    }

    *(result) = (Float_t)nstrip;

    if(!nstrip) return 1;

    mean = mean/nstrip;
    rms  = rms/nstrip - mean * mean ;
    if (rms < 0) return 0;

    *(result+1) = mean;
    *(result+2) = sqrt(rms);
    
    return 1;
    
}

/**
 * Method to evaluate mean value of calibration parameters, over a VA1 chip, a ladder or the whole view.
 * @param what Quantity to evaluate ("PED", "SIG" or "BAD")
 * @param ipkt Stored DSP-packet
 * @param ivk  If ivk=1,24 the average is evaluated for the ivk-th VA1 chip. If ivk=-ladder, where 
 * ladder=1-2, the average is evaluated over the ladder. If ivk=0 the average is evaluated over the whole view.
 */
Float_t TrkCalib::GetMean(TString what, Int_t ipkt, Int_t ivk){

    Float_t* result = new Float_t[3];
    if( !EvaluatePar(what,ipkt,ivk, result) ) return 0.;
    Float_t mean = result[1];
    delete [] result;
    return mean;
}; 
/**
 * Method to evaluate RMS of calibration parameters, over a VA1 chip, a ladder or the whole view.
 * Input parameters follow the same notation of  TrkCalib::GetMean(TString what, Int_t ipkt, Int_t ivk).
 */
Float_t TrkCalib::GetRMS(TString what, Int_t ipkt, Int_t ivk){

    Float_t* result = new Float_t[3];
    if( !EvaluatePar(what,ipkt,ivk, result) ) return 0.;
    Float_t rms = result[2];
    delete [] result;
    return rms;

}; 

/**
 * Method to evaluate RMS of calibration parameters, over a VA1 chip, a ladder or the whole view.
 * Input parameters follow the same notation of  TrkCalib::GetMean(TString what, Int_t ipkt, Int_t ivk).
 */
Float_t TrkCalib::GetNGOOD(Int_t ipkt, Int_t ivk){

    Float_t* result = new Float_t[3];
    if( !EvaluatePar("SIG-BAD",ipkt,ivk, result) ) return 0.;
    Float_t ngood = result[0];
    delete [] result;
    return ngood;

}; 
Float_t TrkCalib::GetNBAD(Int_t ipkt, Int_t ivk){

    Float_t* result = new Float_t[3];

    if( !EvaluatePar("SIG",ipkt,ivk, result) ) return 0.;
    Float_t nbad = result[0];
    if( !EvaluatePar("SIG-BAD",ipkt,ivk, result) ) return 0.;
    nbad = nbad - result[0];
    delete [] result;
    return nbad;

}; 
/**
 * Method to get an array with the calibration-parameters, for a VA1 chip, a ladder or a view. 
 */
Float_t* TrkCalib::Get(TString what, Int_t ipkt, Int_t ivk){

    Int_t from = (ivk-1)*128 ;
    Int_t to= ivk*128;
    if( ivk > 0 && ivk <= 24){
	from = (ivk-1)*128 ;
	to   = ivk*128;
    }else if( ivk==0 ){
	from = 0;
	to   = 3072;
    }else if( ivk < 0 && ivk >= -3 ){
	from = (-ivk-1)*1024;
	to   =  -ivk*1024;
    }else{
	return NULL;
    }
    

    float *pt;

    if(       !what.CompareTo("PED") ){
	pt = (float*)(calib1->DSPped_par);
    }else if( !what.CompareTo("SIG") ){
	pt = (float*)(calib1->DSPsig_par);
    }else{ 
	cout << "TrkCalib::Get(TString what, Int_t ipkt) --> "<<what<<" not implemented\n";
	return NULL;
    };

    return &pt[ipkt*3072+from];
}; 

void TrkCalib::HeaderDump(Int_t ipkt){
    cout << "------------------------"<<endl;
    cout << " DSP "<<calib1->DSPnumber[ipkt]<<endl;
    cout << "------------------------"<<endl;
    cout << "DAQ mode "<<calib1->DAQmode[ipkt]<<endl;
    cout << "<PED>  "<<calib1->ped_l1[ipkt]<<" "<<calib1->ped_l2[ipkt]<<" "<<calib1->ped_l3[ipkt]<<" "<<endl;
    cout << "<SIG>  "<<calib1->sig_l1[ipkt]<<" "<<calib1->sig_l2[ipkt]<<" "<<calib1->sig_l3[ipkt]<<" "<<endl;
    cout << "n.BAD  "<<calib1->nbad_l1[ipkt]<<" "<<calib1->nbad_l2[ipkt]<<" "<<calib1->nbad_l3[ipkt]<<" "<<endl;
    cout << "n.events "<<calib1->ncalib_event[ipkt]<<endl;
    cout << "flag     "<<calib1->cal_flag[ipkt]<<endl;

}
/**
 * Method to get the histogram of calibration-parameters, for a VA1 chip, a ladder or a view. 
 */
TH1F* TrkCalib::GetHisto(TString what, Int_t ipkt, Int_t ivk, Int_t rebin){

    Int_t from = (ivk-1)*128 ;
    Int_t to= ivk*128;
    if( ivk > 0 && ivk <= 24){
	from = (ivk-1)*128 ;
	to   = ivk*128;
    }else if( ivk==0 ){
	from = 0;
	to   = 3072;
    }else if( ivk < 0 && ivk >= -3 ){
	from = (-ivk-1)*1024;
	to   =  -ivk*1024;
    }else{
	return NULL;
    }
    
    TString title ="";
    title.Form(" view %i ",GetView(ipkt));
    title = what + title;
    TH1F* h = new TH1F("h",title.Data(),to-from,from,to);
    Float_t* v = Get(what,ipkt,ivk);
    HeaderDump(ipkt);
    for(Int_t i=from; i<to; i++)h->Fill(i,v[i-from]);
    if(rebin !=0 )h->Rebin(rebin);
    if(rebin !=0 )h->Scale(1./(float)rebin);
    return h;
    
}



ClassImp(TrkCalib);
