//  
//  voltageFit.C
//  Extraction of the mean ratio between the ADC value corresponding to the depletion voltage
//  and the saturation value based on a sigmoid fit
//
//  Created by Christian Elsasser on 31.05.13.
//  University of Zurich, elsasser@cern.ch
//  Copyright only for commercial use
//

//  General include
#include <iostream>
#include <fstream>
#include <vector>
#include <map>
#include <stdlib.h>
#include <limits>
#include <string>
#include <time.h>


//  ROOT include
#include "../../include/incBasicROOT.h"
#include "../../include/incFuncROOT.h"
#include "../../include/incDrawROOT.h"
#include "../../include/incGraphROOT.h"

#include "../../include/incIOROOT.h"


#include "../../include/basicROOTTools.h"


#include "../../include/lhcbstyle.C"


#include "deplTool.h"





int voltageFit(int argc, char* argv[]);


int main(int argc, char* argv[]){
  
  TStyle* style = lhcbStyle();
  
  int argc_copy = argc;
  
  TApplication* theApp = new TApplication("Analysis", &argc, argv);
  argc = theApp->Argc();
  argv = theApp->Argv();
  
  
  bool runBatch = false;
  
  for (int i = 1; i<argc; i++) {
    if (strcmp(argv[i],"-b")==0) {
      runBatch = true;
      gROOT->SetBatch();
    }
  }
  

  
  int exit = voltageFit(argc,argv);
  
  
  
  Printf("End");
  if (!runBatch) {
    theApp->Run(!runBatch);
  }
  
  
  return exit;
}


//  Executable method
int voltageFit(int argc, char* argv[]){
  
  TVectorD v_res(5);
  
  gStyle->SetPadLeftMargin(0.20);
  gStyle->SetTitleOffset(1.5,"Y");
  gStyle->SetTitleOffset(1.0,"X");

  const char* diskVar = std::getenv ("DISK");
  const char* homeVar = std::getenv ("HOME");
  
  int fill      = 1944;
  TString det("TT");
  TString lay("TTaU");
  int val       = 3;
  bool notSave  = false;
  
  for (int i=1; i<argc; i++) {
    if (strcmp(argv[i],"-d")==0 && i+1<argc) {
      det = argv[++i];
    }else if (strcmp(argv[i],"-l")==0 && i+1<argc) {
      lay = argv[++i];
    }else if (strcmp(argv[i],"-v")==0 && i+1<argc) {
      val = std::atoi(argv[++i]);
    }else if (strcmp(argv[i],"-ns")==0) {
      notSave = true;
    }
  }
  
  
  
  
  
  

  
  
  

  
    
  
  Printf("=========================================");
  Info("ratioFit","Analyze: ");
  Printf("               Fill:      %d",fill);
  Printf("               Detector:  %s",det.Data());
  Printf("               Layer:     %s",lay.Data());
  
  
  
  TString dn_vdepl(Form("%s/cmtuser/Vetra_v13r2/ST/STAging/data/db",homeVar));
  TString fn_vdepl(Form("%s/vdepl.root",
                        dn_vdepl.Data()));
  TString dn_fluka(Form("%s/cmtuser/Vetra_v13r2/ST/STAging/data/fluka",homeVar));
  TString fn_fluka(Form("%s/vdepl.root",
                        dn_fluka.Data()));
  
  TFile* f_vdepl    = TFile::Open(fn_vdepl.Data());
  
  
  if (!f_vdepl) {
    Error("ratioFit","File containing V_depl does not exist!");
    Printf("=========================================\n");
    return EXIT_FAILURE;
  }
  
  TVectorD v_sector       = *(TVectorD*)f_vdepl->Get(Form("v_sector_%s",
                                                          lay.Data()));
  TVectorD v_vdepl        = *(TVectorD*)f_vdepl->Get(Form("v_vdepl_%s",
                                                          lay.Data()));
  
  f_vdepl->Close();
  
  Double_t a_tt_excl[18] = {0};
    /*{ 2625,2626,2627,2628,2629,2630,
      2631,2632,2633,2634,2635,2636,
      2637,2638,2639,2640,2641,2642 };*/
      
  
  TVectorD v_tt_excl(sizeof(a_tt_excl)/sizeof(a_tt_excl[0]),a_tt_excl);
  
  
  
  
  TString dn_data(Form("%s/data/ST/Aging"
                        ,diskVar));
  TString fn_data(Form("%s/CCEScan.root",
                       dn_data.Data()));

  TFile* f_data       = TFile::Open(fn_data.Data());
  
  if (!f_data) {
    Error("ratioFit","Data file does not exist!");
    Printf("=========================================\n");
    return EXIT_FAILURE;
  }
  
  TH1F* h_ratio = new TH1F("h_ratio","ratio histo",15,0.7,1.0);
  h_ratio->SetXTitle("ratio");
  h_ratio->SetYTitle(Form("fraction / (%2.2f)",0.02));
  h_ratio->Sumw2();
  
  std::vector<double> v_ratio;
  std::vector<double> v_secRatio;
  
  for (int is = 0; is<v_sector.GetNoElements(); is++) {
    int sector     = (int)v_sector(is);
    double vdepl   = v_vdepl(is);
    
    std::vector<double> v_volt_val;
    std::vector<double> v_volt_err;
    std::vector<double> v_adc_val;
    std::vector<double> v_adc_err;
    
    TString dn_graph(Form("%s/data/ST/graphics/%s/%s/%d/ratio",
                          diskVar,det.Data(),lay.Data(),sector));
    TString fn_graph_p(Form("%s/ratio_volt_val%d",
                            dn_graph.Data(),val));
    
    fn_graph_p += ".pdf";

    
    if (strcmp(det.Data(),"TT")==0) {
      bool skip = false;
      for (int ie=0; ie<v_tt_excl.GetNoElements(); ie++) {
        if ((int)v_tt_excl(ie)==sector) {
          Info("ratioFit","Excluded sector %d skipped!",sector);
          skip = true;
          break;
        }
      }
      if (skip) {
        continue;
      }
    }
    
    Info("ratioFit","Loading data for sector %d:",sector);
    TString dn_input(Form("%s/%s/%d/%d",
                          det.Data(),
                          lay.Data(),
                          sector,
                          fill));
    for (int i=0; i<11; i++) {
      TString vn_input(Form("%s/v_pulse%d_val%d",dn_input.Data(),i,val));
      TVectorD* vp_input = (TVectorD*)f_data->Get(vn_input.Data());
      if (!vp_input) {
        Warning("ratioFit","Vector %s not available",vn_input.Data());
        continue;
      }
      
      double volt = 0.0;
      
      if (det.EqualTo("TT")) {
        volt = STTool::GetTTVoltage(i*6);
      }else{
        volt = STTool::GetITVoltage(i*6);
      }
      
      if (det.EqualTo("IT") && volt>250.0) {
        continue;
      }
      
      TVectorD v_input = (*vp_input);
      
      double height_val = v_input(0);
      double height_err = v_input(1);
      
      //    height_val *= v_input(2)*v_input(2)*9.0/2.0*TMath::Exp(-3.0)/(250.0);
      //
      //    height_err  = height_val*TMath::Sqrt(TMath::Power(height_err/height_val,2)+
      //					 TMath::Power(2*v_input(3)/v_input(2),2)+
      //					 2*v_input(8)/(height_val*v_input(2)));
      
      if (det.EqualTo("IT")) {
        height_val /= 0.1306; // transform back to the amplitude
        height_err /= 0.1306; // transform back to the amplitude
        height_val *= v_input(2)*9.0/2.0*TMath::Exp(-3.0)/(20.0);
        height_err  = height_val*TMath::Sqrt(TMath::Power(height_err/height_val,2)+
                                             TMath::Power(v_input(3)/v_input(2),2)+
                                             2*v_input(8)/(height_val*v_input(2)));
      }

      
      //    height_val *= v_input(2)*v_input(2)*9.0/2.0*TMath::Exp(-3.0)/(250.0);
      //
      //    height_err  = height_val*TMath::Sqrt(TMath::Power(height_err/height_val,2)+
      //					 TMath::Power(2*v_input(3)/v_input(2),2)+
      //					 2*v_input(8)/(height_val*v_input(2)));
      
      
//      if (v_input(2)>20.0) {
//        height_val = v_input(0);
//        height_err = v_input(1);
//      }
      
      Printf("        %8.2f V: %8.4f+/-%8.4f",volt,height_val,height_err);
      
      
      v_adc_val.push_back(height_val);
      v_adc_err.push_back(height_err);
      v_volt_val.push_back(volt);
      v_volt_err.push_back(0.0);
      
    }
    
    if (v_adc_val.size()<3) {
      Error("ratioFit","Too few (%d) data points",v_adc_val.size());
      continue;
    }
    
    
    TVectorD vr_adc_val  = getROOTVector(v_adc_val);
    TVectorD vr_adc_err  = getROOTVector(v_adc_err);
    TVectorD vr_volt_val = getROOTVector(v_volt_val);
    TVectorD vr_volt_err = getROOTVector(v_volt_err);
    
    TGraphErrors* ge_volt = new TGraphErrors(vr_volt_val,vr_adc_val,vr_volt_err,vr_adc_err);
    
    TMultiGraph* mg_volt = new TMultiGraph("mg_volt","Voltage multigraph");
    
    
    
    
    TF1* fu_volt = STTool::sigmoid4;
    
    
    
    ge_volt->Fit(fu_volt,"M0Q","0");
    
    double chi2ndf = fu_volt->GetChisquare()/fu_volt->GetNDF();
    Info("voltageFit","#chi^{2}/ndf: %6.2f/%d",fu_volt->GetChisquare(),fu_volt->GetNDF());
    if (chi2ndf>1.0) {
      Info("voltageFit","scaling");
      vr_adc_err*=TMath::Sqrt(chi2ndf);
    }
    
    
    ge_volt = new TGraphErrors(vr_volt_val,vr_adc_val,vr_volt_err,vr_adc_err);
    ge_volt->Fit(fu_volt,"M0Q","0");
    
    TVirtualFitter *fit_volt = TVirtualFitter::GetFitter();
    Double_t* cov_volt       = fit_volt->GetCovarianceMatrix();
    
    int nPar = fu_volt->GetNpar();
    
    double adc_err = 0.0;
    for (Int_t j=0; j<nPar; j++) {
      for (Int_t k=0; k<nPar; k++) {
        if (strcmp(fu_volt->GetParName(j),"A_{0}")==0 || strcmp(fu_volt->GetParName(k),"A_{0}")==0) {
          continue;
        }
        adc_err += cov_volt[nPar*j+k]*fu_volt->GradientPar(j,&vdepl)*fu_volt->GradientPar(k,&vdepl);
      }
    }
    adc_err = TMath::Sqrt(adc_err);
    
    mg_volt->Add(ge_volt,"pe");
    
    double frac     = fu_volt->Eval(vdepl)/fu_volt->GetParameter("A_{0}");
    double frac_err = adc_err/fu_volt->GetParameter("A_{0}");
    
    TCanvas* c_vol = new TCanvas("c_vol","Voltage Canvas",800,600);
    
    double maxX = 500.0;
    
    if (det.EqualTo("IT")){
      maxX = 250.0;
    }
        
      
      
    mg_volt->Draw("A");
    mg_volt->GetXaxis()->SetLimits(0.0,maxX);
    mg_volt->GetXaxis()->SetTitle("#it{V}_{bias} [V]");
    mg_volt->SetMaximum(50.0);
    mg_volt->SetMinimum(0.0);
    mg_volt->GetYaxis()->SetTitle("Max. signal height [ADC value]");
    
    TLine* val_line = new TLine(vdepl,0.0,vdepl,fu_volt->Eval(vdepl));
    val_line->Draw();
    val_line = new TLine(0.0,fu_volt->Eval(vdepl),vdepl,fu_volt->Eval(vdepl));
    val_line->Draw();
    
    fu_volt->Draw("Same");
    mg_volt->Draw("");
    
    
    mg_volt->GetHistogram()->Draw("axissame");
    
    
    if (!notSave) {
      // Save picture
      gSystem->Exec(Form("mkdir -p %s",dn_graph.Data()));
      gSystem->Exec(Form("rm %s &> /dev/null",fn_graph_p.Data()));
      c_vol->SaveAs(fn_graph_p.Data());
    }
    
    if (adc_err>0.2 && !TMath::IsNaN(adc_err)) {
      h_ratio->Fill(frac,1.0/(adc_err));
    }

    Info("ratioFit","ratio: %9.6f",frac);
    
    v_ratio.push_back(frac);
    v_secRatio.push_back(sector);
    
    
    delete c_vol;
  }
  
  h_ratio->Scale(1.0/h_ratio->Integral());
  h_ratio->SetMarkerColor(kRed);
  h_ratio->SetLineColor(kRed);
  
  h_ratio->SetLabelOffset(0.02,"X");
  TCanvas* c_ratio = new TCanvas("c_ratio","Ratio plot",800,600);
  h_ratio->Draw("");
  
  Info("ratioFit","Ratio for %s: %4.3f+/-%4.3f",
       lay.Data(),h_ratio->GetMean(),h_ratio->GetRMS());
  
  TString dn_output(Form("%s/cmtuser/Vetra_v13r2/ST/STAging/data/db",homeVar));
  TString fn_output(Form("%s/ratio.root",
                         dn_output.Data()));
  
  TVectorD vr_ratio       = getROOTVector<double>(v_ratio);
  TVectorD vr_secRatio    = getROOTVector<double>(v_secRatio);
  
  TFile* f_output = new TFile(fn_output.Data(),"UPDATE");
  
  TString vn_ratio     = TString::Format("v_ratio_%s",lay.Data());
  TString vn_secRatio  = TString::Format("v_sector_%s",lay.Data());
  
  f_output->Delete(Form("%s;*",vn_ratio.Data()));
  f_output->Delete(Form("%s;*",vn_secRatio.Data()));
  
  vr_ratio.Write(vn_ratio.Data());
  vr_secRatio.Write(vn_secRatio.Data());
  
  f_output->Close();
  
  Info("ratioFit","Data written to %s",fn_output.Data());
  
  
  Printf("=========================================\n");

  return EXIT_SUCCESS;
}


