/*Script to extract reference time "t0"  for each sense wire in a given HMS Wire Chamber Plane with COSMIC RUNS.  
20% (MAX BIN CONTENT) is calculated per wire, and the corresponding bin is fitted linearly about +/- 
a certain number of bins and this fit is extrapolated to y=0(x-axis). The extrapolated value is take to be t0*/

#include <vector>
#include "TMath.h"
#include <iomanip>
#include <iostream>

#define NPLANES 12
  using namespace std;
void get_wire_tzero()
{
 

  int run_NUM;
  Long64_t num_evts;        //added
  string input_file;   //added

  TString f0 = "input_RUN.txt";
  ifstream infile(f0);
  infile >> input_file >> run_NUM >> num_evts;   //read the input file (added)   

  //check if tzero_weighted_avg text file exists (if it does, DELETE IT, otherwise new values will be appended to it, in addition to pre-existing tzero values)
  std::ifstream stream(Form("../data_files/run%d/tzero_weighted_avg_run%d.dat",run_NUM, run_NUM));
 if (stream.good())
  {
  gSystem->Exec(Form("rm ../data_files/run%d/tzero_weighted_avg_run%d.dat",run_NUM, run_NUM));
  }

 TString run = Form("run%d", run_NUM);

 //Declare plane names to loop over
 TString plane_names[NPLANES]={"1u1", "1u2", "1x1", "1x2", "1v1", "1v2", "2v2", "2v1", "2x2", "2x1", "2u2", "2u1"};
 int fNWires[NPLANES] = {107, 107, 79, 79, 107, 107, 107, 107, 79, 79, 107, 107};

 //Declare a root file array to store individual DC cell drift times
 TString root_file;
 TFile *f[NPLANES];
   
 // int total_wires;  //integer to store total sense wires for a plane chosen by the user
        
 //Loop over all planes
 for (int ip = 0; ip < NPLANES; ip++){

   //READ root file
   root_file = "../root_files/"+run+"/shms_DC_"+plane_names[ip]+Form("_%d_wire_histos.root",run_NUM);
   f[ip] = new TFile(root_file, "READ");

   //Create a file output file stream object to write t0 values to data file
   ofstream ofs;
   TString t_zero_file = "../data_files/" + run + "/shms_dc_"+plane_names[ip]+Form("tzero_run%d.dat", run_NUM);
   ofs.open (t_zero_file);

   //Set headers for subsequent columns of data
   ofs << "#WIRE " << setw(15)  << "t0" << setw(15) << "t0_err" << setw(15) << "entries" << endl;

   //Create root file to store fitted wire drift times histos and "t0 vs. wirenum"
   TString output_root_file = "../root_files/"+run+"/shms_DC_"+plane_names[ip]+Form("_%d_fitted_histos.root", run_NUM);
   TFile *g = new TFile(output_root_file,"RECREATE");

   f[ip]->cd();  //change to file containing the wire drift times histos
 
   //   int total_wires;  //integer to store total sense wires for a plane chosen by the user

   //INITIALIZE VARIABLES
   int total_wires;
   int sensewire;
   TH1F *cell_dt[107];
   Int_t *bin_max;
   Int_t *bin_maxContent;
   Double_t *time_max;
   Double_t *twenty_perc_maxContent;
   Double_t *ref_time;



     //Declarations
     int time_init;           //start fit value 
     int time_final;          //end fit value
     int t_zero;
     int entries;             //entries for each wire
     
     double m;                //slope
     double y_int;            //y-intercept
     double m_err;
     double y_int_err;
     double t_zero_err;

   //Set variables depending on which plane is being studied
   if(ip == 0 || ip == 1 || ip == 4 || ip == 5 || ip == 6 || ip == 7 || ip == 10 || ip == 11) {
     //declare array of histos to store drift times     
     total_wires=107; 

     //Declare bin properties for given sense wires in a plane

     bin_max = new Int_t[total_wires];                    /*Array to store the bin number corresponding to the drift time distribution peak*/
     bin_maxContent= new Int_t[total_wires];             /*Array to store the content (# events) corresponding to the bin with maximum content*/
     time_max= new Double_t[total_wires];                /*Array to store the x-axis(drift time (ns)) corresponding to bin_max*/
     twenty_perc_maxContent= new Double_t[total_wires];  /*Array to store 20% of maximum bin content (peak)*/						     
     ref_time= new Double_t[total_wires];               /*Array to store reference times for each sense wire*/

   }
   
   else if(ip == 2 || ip == 3 || ip == 8 || ip == 9) {
     total_wires=79;      
     bin_max = new Int_t[total_wires];                               
     bin_maxContent= new Int_t[total_wires]; 
     time_max= new Double_t[total_wires];
     twenty_perc_maxContent= new Double_t[total_wires];
     ref_time= new Double_t[total_wires];
   }	   
   
 	
   /*Get wire histos from root file and loop over each 
     sense wire of a plane in shms Drift Chambers (DC1 or DC2)*/
 
   for (sensewire=1; sensewire<=total_wires; sensewire++){

     //Get title of histos in root file
     TString drift_time_histo = Form("wire_%d", sensewire); 
 
     //Get drift time histograms from root file
     cell_dt[sensewire-1] = (TH1F*)f[ip]->Get(drift_time_histo);

     
     //Get bin with Maximum Content
     bin_max[sensewire-1] = cell_dt[sensewire-1]->GetMaximumBin();

     //Get content of bin_max
     bin_maxContent[sensewire-1] = cell_dt[sensewire-1]->GetBinContent(bin_max[sensewire-1]);
     
     //Get time (ns) [x-axis] corresponding to bin_max 
     time_max[sensewire-1] = cell_dt[sensewire-1]->GetXaxis()->GetBinCenter(bin_max[sensewire-1]);
     
     //Calculate 20% of max content
     twenty_perc_maxContent[sensewire-1] = bin_maxContent[sensewire-1] * 0.20;
     

   }
   
   
   
   //****************************************************//
   //Determine  which bin has around 20% max_BinContent *//
   //****************************************************//
   
   
   //Declarations
   int content_bin;      //stores content for each bin
   int counts;           //a counter used to count the number of bins that have >20% max bin content for a plane 
   int bin;              //store bin number
   int j;                //jth bin, used to loop over n bins 
   
   //Declare vector arrays 
   vector<int> content;               //stores bin content
   vector <int> bin_num;           //stores bin number
   
   
   //Loop over each wire 
   for(sensewire=1; sensewire<=total_wires; sensewire++) {
     
     //Loop over each bin for individual wire drift time histo
     for(bin=0; bin < bin_max[sensewire-1]; bin++) {
       
       content_bin = cell_dt[sensewire-1]->GetBinContent(bin);              //get bin content for all bins in a wire
       
       content.push_back(content_bin);                                      //add bin content to array
       bin_num.push_back(bin);                                              //add bin number to array
       
       
       // check if 2 bin contents have been stored and examine if these contents exceed or not 20% of peak
       if (content.size() == 2) {
	 
	 //initialize counter to count how many bin contents >= 20%
	 counts = 0;
	 
	 // Loop over 2 bin contents stored in array content
	 for (j=0; j<2; j++){
	   
	   if(content[j] >=  twenty_perc_maxContent[sensewire-1]){
	     counts = counts+1;
             
	     if(counts >= 2) { goto stop;}
	     
	     
	   }
	   
	   content.clear();
	   bin_num.clear();
	   
	 }
	 
       }
     }
     
     //Print the time(ns) and BIN NUM corresponding to 20% of MAX content 
     //if 2/2 elements exceeds 20% of Max content (for each plane)
     
   stop:
     ref_time[sensewire-1] = cell_dt[sensewire-1] ->GetXaxis() -> GetBinCenter(bin_num[0]); //Get time corresponding ~20% Max BIN CONTENT  
     
     //cout << " ******* " << "Wire " << sensewire << " ******* " << endl;
     //cout << "time (20% of Max BIN): " << ref_time[sensewire-1] << " ns" << endl;
     //cout << "BIN: " << bin_num[0] << endl;
     
     
     //*********************************************************//
     //*******Extract the "t0" Using a Fitting Procedure********//
     //*********************************************************//
     

     
     //Get time corresponding to bin (fit range) 
     time_init = cell_dt[sensewire-1] -> GetXaxis() -> GetBinCenter(bin_num[0]-5); //choose bin range over which to fit
     time_final = cell_dt[sensewire-1] -> GetXaxis() -> GetBinCenter(bin_num[0]+5); 
     
     //Create Fit Function
     TF1* tZero_fit = new TF1("tZero_fit", "[0]*x + [1]", time_init, time_final);
     
     //Set Parameter Names and Values
     tZero_fit->SetParName(0, "slope");
     tZero_fit->SetParName(1, "y-int");
     tZero_fit->SetParameter(0, 1.0);
     tZero_fit->SetParameter(1, 1.0);
     
     //Fit Function in specified range
     cell_dt[sensewire-1]->Fit("tZero_fit", "QR");
     
     //Get Parameters and their errors
     m = tZero_fit->GetParameter(0);
     y_int = tZero_fit->GetParameter(1);
     m_err = tZero_fit->GetParError(0);
     y_int_err = tZero_fit->GetParError(1);
     
     //Calculate error on t0 using error propagation method of expanding partial derivatives
     t_zero = - y_int/m;
     t_zero_err = sqrt(y_int_err*y_int_err/(m*m) + y_int*y_int*m_err*m_err/(m*m*m*m) );
     entries = cell_dt[sensewire-1]->GetEntries();  //number of entries (triggers) per wire
     //cout << "y_int: " << y_int << " :: " << "m: " << m << " :: " << "t0: " << setprecision(6) << -y_int/m << endl;
     //Write "t0" values to file
     ofs << sensewire << setw(15) << setprecision(6) << -y_int/m << setw(15) <<  t_zero_err << setw(15) << entries << endl;
     
     //Change to output root file and write fitted histos to file
     g->cd();
     cell_dt[sensewire-1]->Write();
     
   }
   
       // Make Plot of t0 versus Wire Number 
   
   TCanvas *t = new TCanvas("t", "", 2000,500);
   t->SetGrid();

   
   TGraphErrors *graph = new TGraphErrors(t_zero_file, "%lg %lg %lg");
   graph->SetName("graph");
   TString title = "DC"+plane_names[ip]+": t0 versus sensewire";
   graph->SetTitle(title);
   graph->SetMarkerStyle(20);
   graph->SetMarkerColor(1);
   graph->GetXaxis()->SetLimits(0., total_wires);
   graph->GetXaxis()->SetTitle("Wire Number");
   graph->GetXaxis()->CenterTitle();
   graph->GetYaxis()->SetTitle("t-Zero (ns)");
   graph->GetYaxis()->CenterTitle();
   graph->GetYaxis()->SetRangeUser(-50.0, 50.0);
   graph->Draw("AP");
   t->Update();
   t->Write(title);   //write to a root file
  
   
   //close dat file
   ofs.close();
   
   //*****************************************************************************************//
   //        CALCULATE THE "t0s" WEIGHTED AVERAGE FOR WIRE DRIFT TIMES WITH ENTRIES > = 300   //
   //*****************************************************************************************//
   
   
   //open t0 dat file
   ifstream ifs;
   ifs.open (t_zero_file);
   string line;
   
   //open new data file to write updated t0 values
   TString t_zero_file_corr = "../data_files/" + run + "/shms_dc_"+plane_names[ip]+Form("tzero_run%d_updated.dat", run_NUM);
   ofs.open(t_zero_file_corr);
   ofs << "#Wire" << setw(15)  << "t_zero" << setw(15) << "t_zero_err" << setw(15) << "entries" << endl; 
   
   //Initialize variables related to weighted avg
   double sum_NUM;  //numerator of weighted avg
   double sum_DEN;   //denominator of weighted avg
   double weighted_AVG;
   double weighted_AVG_err; 
  
    int counter;
    // double t0_corr; 
    //double t0_corr_err;
    Double_t t0;
    Double_t t0_err;

    //set them to zero to start sum inside while loop 
   sum_NUM = 0.0;
   sum_DEN = 0.0;
   
   weighted_AVG =0.0 ;
   weighted_AVG_err= 0.0; 
   
   counter = 0;
   //read line bt line the t_zero_file
   while(getline(ifs, line)) {

     if(line[0]!='#') {
       
       sscanf(line.c_str(), "%d %lf %lf %d", &sensewire, &t0, &t0_err, &entries); //assign each of the variables above a data in the t_zero_file

       //  if(sensewire<=fNWires[ip]){
	
       cout << sensewire << endl;
     //Check if entries for each sensewire exceeds a certain number of events
     
       if (entries>300 && abs(t0)<30) 
       {

	 //cout << ip << "::" << sensewire << "::" << t0 << endl;
	 //Calculate the weighted average of t0s
	 sum_NUM = sum_NUM + t0/(t0_err*t0_err);
	 sum_DEN = sum_DEN + 1.0/(t0_err*t0_err);      
	 
	 //cout << "sum_NUM : " << sum_NUM << endl;  
	 //cout << "sum_DEN : " << sum_DEN << endl;  
	 
	 

	 
	 ofs << sensewire << setw(15) << t0 << setw(15) << t0_err << setw(15) << entries << endl;
	 //cout << "TZERO: " << t0 << endl;
	 
	 

       }
     
     else { ofs << sensewire << setw(15) << 0.0 << setw(15) << 0.0 << setw(15) << entries << endl;}
     
     //}
     
     } //end if statement
   }
   
   
   
   weighted_AVG = sum_NUM / sum_DEN;
   weighted_AVG_err = sqrt( 1.0 / sum_DEN );
   
   
   
   //open new data file to write weighted average of updated t_zero values
   
   TString t_zero_AVG = Form("../data_files/run%d/tzero_weighted_avg_run%d.dat", run_NUM, run_NUM);
   
   ofstream ofile;
   ofile.open(t_zero_AVG, std::ofstream::out | std::ofstream::app); //open file in and output and append mode
   
   ofile << " #weighted_AVG " << "     " << " DC plane: " <<  plane_names[ip] << endl; 
   ofile << weighted_AVG << endl;
     
   
   ifs.close();

    // Make Plot of t0 versus Wire Number for entries > 300 events
   
   TCanvas *t1 = new TCanvas("t1", "", 2000,500);
   t1->SetGrid();

   //TString mygraph = "hdc"+plane_names[ip]+Form("_t_zero_run%d.txt", run);
   TGraphErrors *graph1 = new TGraphErrors(t_zero_file_corr, "%lg %lg %lg");
   graph1->SetName("graph1");
   TString title1 = "shms_dc"+plane_names[ip]+": t0 versus sensewire_corrected";
   graph1->SetTitle(title1);
   graph1->SetMarkerStyle(20);
   graph1->SetMarkerColor(1);
   //graph1->GetXaxis()->SetLimits(0., total_wires);
   graph1->GetXaxis()->SetTitle("Wire Number");
   graph1->GetXaxis()->CenterTitle();
   graph1->GetYaxis()->SetTitle("t-Zero (ns)");
   graph1->GetYaxis()->CenterTitle();
   graph1->GetYaxis()->SetRangeUser(-50.0, 50.0);
   graph1->Draw("AP");
   t1->Update();

   // Draw TLine
   TLine *wght_avg = new TLine(t1->GetUxmin(), weighted_AVG, t1->GetUxmax(), weighted_AVG);
   wght_avg->SetLineColor(kRed);
   wght_avg->SetLineWidth(2);
   wght_avg->SetLineStyle(2);
   wght_avg->Draw();
   
   //Add text to canvas
   TLatex* ltx1 =  new TLatex();
   ltx1->DrawLatex(t1->GetUxmax()*0.75,40, Form("Weighted Average = %lf #pm %lf ns", weighted_AVG, weighted_AVG_err) );
   
   t1->Write(title1);   //write canvas to a root file
 
      ofs.close();  //close data file









 }
 
 




}