//************************************************
// Author: Federica Lionetto
// Created on: 03/11/2014
//************************************************

/*
ProcessRawData reads a ROOT file (containing the raw data to process) and a text file (containing the pedestals) and creates a ROOT file with the following information:
- all branches in the Header tree;
- all branches in the EventInfo tree, one per event;
- string InputFilename, the complete path to the input file (ROOT file);
- string PedFilename, the complete path to the pedestal file (text file);
- std::vector<float> Ped, the pedestals calculated by ComputePedestals;
- std::vector<float> ADCProcessed, one per event (ADC after pedestal subtraction);
- distribution of the ADC counts of each Beetle (TH1F *hADCBeetle1 and TH1F *hADCBeetle2, before pedestal subtraction, and TH1F *hADCPedSubBeetle1 and TH1F *hADCPedSubBeetle2, after pedestal subtraction);
- distribution of the ADC counts of each Beetle channel (TH1F *hADC[N], before pedestal subtraction, and TH1F *hADCPedSub[N], after pedestal subtraction);
- ADC counts as a function of the Beetle channel (event-by-event, displayed only for one particular event, TH1F *hADCvsStripBeetle1 and TH1F *hADCvsStripBeetle2, before pedestal subtraction, and TH1F *hADCPedSubvsStripBeetle1 and TH1F *hADCPedSubvsStripBeetle2, after pedestal subtraction).

Compile with:

make

Run with:

./ProcessRawData [input ROOT file] [input text file (pedestals)] [additional folder]

where:
- [input ROOT file] is the complete path, including the folder and the filename, of the ROOT file one wants to process;
- [input text file (pedestals)] is the complete path, including the folder and the filename, of the text file one wants to get the pedestals from;
- [additional folder] is the optional additional folder where the output will be saved.
*/

#include "../Tools/Lib.C"
#include "../Tools/lhcbStyle.C"
#include "../Tools/Style.C"

#include "../Tools/Par.C"

void ProcessRawData(char *filename, char *filenamePed, char *externalPath=0);

int main(int argc, char *argv[])
{
  getLHCbStyle();
  PersonalStyle();

  if ((argc ==2) && (string(argv[1]) == "--info"))
  {
    cout << "**************************************************" << endl;

    cout << "Some comments." << endl;
    
    cout << "**************************************************" << endl;

    return 0;
  }
  else if (argc < 3)
  {
    cout << "**************************************************" << endl;
    
    cout << "Error! Input file or pedestal file missing..." << endl;
    cout << "Please use the following format:" << endl;
    cout << "./ProcessRawData [1] [2] [3]" << endl;
    cout << "with:" << endl;
    cout << "[1] = Input ROOT file, complete path;" << endl;
    cout << "[2] = Input text file (pedestals), complete path;" << endl;
    cout << "[3] = Additional folder, optional." << endl;
    cout << "Type ./ProcessRawData --info for more information." << endl;

    cout << "**************************************************" << endl;

    return 0;  
  }
  else
  {
    cout << "File to process: " << argv[1] << endl;
    cout << "Pedestal file: " << argv[2] << endl;
    if (argc == 3)
      ProcessRawData(argv[1],argv[2]);
    else if (argc == 4)
      ProcessRawData(argv[1],argv[2],argv[3]);
    else
    {
      cout << "Error! Too many arguments given..." << endl;
      
      return 0;
    }
    
    return 0;  
  }  
}

void ProcessRawData(char *filename, char *filenamePed, char *externalPath)
{
  cout << "**************************************************" << endl;
  cout << "Processing raw data..." << endl;
  cout << "**************************************************" << endl;
 
  // Do not comment this line.
  gROOT->ProcessLine("#include <vector>");

  // Do some fanciness to get the directory right.
  // string analysis = "/home/hep/flionett/TestStand/AnalysisResults";
  string analysis = "/disk/groups/hep/flionett/TestStand/AnalysisResults";
  if (externalPath!=0)
    analysis = string(analysis+"/"+externalPath);

  string filename_as_string = string(filename);
  // Check that the filename provided corresponds to a ROOT file.
  int found = filename_as_string.find(".root");
  if (found==string::npos)  {
    cout << "Error! The filename provided is not associated to a ROOT file." << endl;
    return;
  }

  string filename_as_string_no_path = filename_as_string.substr(filename_as_string.find_last_of('/')+1);
  string filename_as_string_no_path_no_extension = filename_as_string_no_path.substr(0,filename_as_string_no_path.length()-5);

  // Create a folder named AnalysisResults. Do not worry, nothing bad is going to happen if the folder already exists.
  string path_to_make = "mkdir -p "+analysis;
  system(path_to_make.c_str());
  cout << "Setting output to: " << path_to_make << endl;

  // Create a folder named Figures inside the folder named AnalysisResults.
  string path_to_make_figures = "mkdir "+analysis+"/Figures";
  system(path_to_make_figures.c_str());
  path_to_make_figures = "mkdir "+analysis+"/Figures"+"/ProcessRawData";
  system(path_to_make_figures.c_str());
  path_to_make_figures = "mkdir "+analysis+"/Figures"+"/ProcessRawData"+"/"+filename_as_string_no_path_no_extension;
  system(path_to_make_figures.c_str());
  cout << "Setting figures to: " << path_to_make_figures << endl;  

  TString path_to_figures = (string(path_to_make_figures)).substr((string(path_to_make_figures)).find_last_of(' ')+1);

  // Open input data ROOT file.
  TFile *input = TFile::Open(TString(filename));

  int NEvents;

  std::vector<unsigned short> *ADC = 0;

  TBranch *b_NEvents = 0;
  
  TBranch *b_ADC = 0;

  // Get info from trees.
  TTree *Header = (TTree *)input->Get("Header");
  int EventsHeader = Header->GetEntries();
  if (EventsHeader != 1)
  {
    cout << "Error! The ROOT file has been corrupted..." << endl;

    return ;
  }
  else 
  {
    Header->SetBranchAddress("NEvents",&NEvents,&b_NEvents);

    Header->GetEntry();

    cout << "Number of events: " << NEvents << endl;
  }

  // Get info from trees.
  TTree *EventInfo = (TTree *)input->Get("EventInfo");
  int EventsEventInfo = EventInfo->GetEntries();
  if (EventsEventInfo != NEvents)
  {
    cout << "Error! The ROOT file has been corrupted..." << endl;

    return;
  }
  else 
  {
    EventInfo->SetBranchAddress("ADC",&ADC,&b_ADC);
  }

  // Open input pedestal text file.
  FILE *inputText = fopen(TString(filenamePed),"r");

  // Read pedestals.
  float ped[N];
  
  for (int iChannel=0; iChannel<N; ++iChannel) {
    fscanf(inputText,"%*d%*c%f%*c%*f%*c%*f%*c%*f%*c",&(ped[iChannel]));
    // cout << iChannel << ", " << ped[iChannel] << endl;
  }
  
  // Close input pedestal text file.
  fclose(inputText);

  // Open output data ROOT file.
  TFile *output = TFile::Open(analysis+"/ProcessRawData-"+TString(filename_as_string_no_path),"RECREATE");

  // Copy the Header tree to the output data ROOT file and add some more information.
  string InputFilename;
  string PedFilename;
  std::vector<float> Ped;

  InputFilename = string(filename);
  PedFilename = string(filenamePed);

  for (int iChannel=0; iChannel<N; ++iChannel)
  {
    Ped.push_back(ped[iChannel]);
  }
  TTree *HeaderProcessed = Header->CloneTree(0);
  HeaderProcessed->Branch("InputFilename",&InputFilename);
  HeaderProcessed->Branch("PedFilename",&PedFilename);
  HeaderProcessed->Branch("Ped",&Ped);
  HeaderProcessed->Fill();

  // Show the distributions for one particular event.
  int sample = 970; // Modify it.
  
  // Copy the EventInfo tree to the output data ROOT file and add some more information.
  std::vector<float> ADCProcessed; // Raw ADC - pedestal.

  TTree *EventInfoProcessed = EventInfo->CloneTree(0);
  EventInfoProcessed->Branch("ADCProcessed",&ADCProcessed);
  
  // Distribution of the ADC counts of each Beetle (TH1F *hADCBeetle1 and TH1F *hADCBeetle2, before pedestal subtraction, and TH1F *hADCPedSubBeetle1 and TH1F *hADCPedSubBeetle2, after pedestal subtraction);

  TH1F *hADCBeetle1 = new TH1F("hADCBeetle1","",400,300,700); // Modify it.
  TCanvas *cADCBeetle1 = new TCanvas("cADCBeetle1","",400,300);
  InitHist(hADCBeetle1,"Raw ADC counts on Beetle 1","ADC counts","");

  TH1F *hADCPedSubBeetle1 = new TH1F("hADCPedSubBeetle1","",200,-100,100); // Modify it.
  TCanvas *cADCPedSubBeetle1 = new TCanvas("cADCPedSubBeetle1","",400,300);
  InitHist(hADCPedSubBeetle1,"Pedestal subtracted ADC counts on Beetle 1","ADC counts","");

  TH1F *hADCBeetle2 = new TH1F("hADCBeetle2","",400,300,700); // Modify it.
  TCanvas *cADCBeetle2 = new TCanvas("cADCBeetle2","",400,300);
  InitHist(hADCBeetle2,"Raw ADC counts on Beetle 2","ADC counts","");

  TH1F *hADCPedSubBeetle2 = new TH1F("hADCPedSubBeetle2","",200,-100,100); // Modify it.
  TCanvas *cADCPedSubBeetle2 = new TCanvas("cADCPedSubBeetle2","",400,300);
  InitHist(hADCPedSubBeetle2,"Pedestal subtracted ADC counts on Beetle 2","ADC counts","");

  // Distribution of the ADC counts of each Beetle channel (TH1F *hADC[N], before pedestal subtraction, and TH1F *hADCPedSub[N], after pedestal subtraction);

  TH1F *hADC[N];
  TCanvas *cADC[N];

  TH1F *hADCPedSub[N];
  TCanvas *cADCPedSub[N];

  for (int iChannel=0;iChannel<N;++iChannel) {
    hADC[iChannel] = new TH1F(Form("hADC%d",iChannel),"",1024,0,1024);
    cADC[iChannel] = new TCanvas(Form("cADC%d",iChannel),"",400,300);
    
    InitHist(hADC[iChannel],Form("Raw ADC counts on Beetle channel %d",iChannel),"ADC counts","");

    hADCPedSub[iChannel] = new TH1F(Form("hADCPedSub%d",iChannel),"",1024,-512,512);
    cADCPedSub[iChannel] = new TCanvas(Form("cADCPedSub%d",iChannel),"",400,300);
    
    InitHist(hADCPedSub[iChannel],Form("Pedestal subtracted ADC counts on Beetle channel %d",iChannel),"ADC counts","");
  }

  // ADC counts as a function of the Beetle channel (event-by-event, displayed only for one particular event, TH1F *hADCvsStripBeetle1 and TH1F *hADCvsStripBeetle2, before pedestal subtraction, and TH1F *hADCPedSubvsStripBeetle1 and TH1F *hADCPedSubvsStripBeetle2, after pedestal subtraction).

  TH1F *hADCvsStripBeetle1 = new TH1F("hADCvsStripBeetle1","",128,0,128);
  TCanvas *cADCvsStripBeetle1 = new TCanvas("cADCvsStripBeetle1","",400,300);

  TH1F *hADCvsStripBeetle2 = new TH1F("hADCvsStripBeetle2","",128,128,256);
  TCanvas *cADCvsStripBeetle2 = new TCanvas("cADCvsStripBeetle2","",400,300);
 
  InitHist(hADCvsStripBeetle1,Form("Event %d - Beetle 1, raw",sample),"Beetle channel","ADC counts");
 
  InitHist(hADCvsStripBeetle2,Form("Event %d - Beetle 2, raw",sample),"Beetle channel","ADC counts");

  TH1F *hADCPedSubvsStripBeetle1 = new TH1F("hADCPedSubvsStripBeetle1","",128,0,128);
  TCanvas *cADCPedSubvsStripBeetle1 = new TCanvas("cADCPedSubvsStripBeetle1","",400,300);

  TH1F *hADCPedSubvsStripBeetle2 = new TH1F("hADCPedSubvsStripBeetle2","",128,128,256);
  TCanvas *cADCPedSubvsStripBeetle2 = new TCanvas("cADCPedSubvsStripBeetle2","",400,300);
 
  InitHist(hADCPedSubvsStripBeetle1,Form("Event %d - Beetle 1, ped sub",sample),"Beetle channel","ADC counts");
 
  InitHist(hADCPedSubvsStripBeetle2,Form("Event %d - Beetle 2, ped sub",sample),"Beetle channel","ADC counts");

  // Style and range for Beetle 1 plots.
  hADCvsStripBeetle1->SetFillColor(kAzure);
  hADCPedSubvsStripBeetle1->SetFillColor(kAzure);
  hADCvsStripBeetle1->SetMinimum(0);
  hADCvsStripBeetle1->SetMaximum(1200);
  hADCPedSubvsStripBeetle1->SetMinimum(-150);
  hADCPedSubvsStripBeetle1->SetMaximum(900);

  // Style and range for Beetle 2 plots.
  hADCvsStripBeetle2->SetFillColor(kRed);
  hADCPedSubvsStripBeetle2->SetFillColor(kRed);
  hADCvsStripBeetle2->SetMinimum(0);
  hADCvsStripBeetle2->SetMaximum(1200);
  hADCPedSubvsStripBeetle2->SetMinimum(-150);
  hADCPedSubvsStripBeetle2->SetMaximum(900);

  // Fill histograms.
  for (int iEvent=0;iEvent<NEvents;++iEvent) {
    if (iEvent%1000==0)
      cout << "Processing Event " << iEvent << endl;

    // Initialize histograms.
    if (iEvent>0) 
    {
      ADCProcessed.clear();
    }    
    
    EventInfo->GetEntry(iEvent);
    
    // Fill histograms.
    for (int iChannel=0;iChannel<N;++iChannel) { 
      if (ADC->at(iChannel) > 1024.)
	cout << "Error! ADC counts of Beetle channel " << iChannel << ": " << ADC->at(iChannel) << endl; 
      
      ADCProcessed.push_back((float)ADC->at(iChannel)-ped[iChannel]);
      
      if ((iChannel>=0) && (iChannel<NBeetle))
      {
	hADCBeetle1->Fill((float)ADC->at(iChannel));
	hADCPedSubBeetle1->Fill((float)ADC->at(iChannel)-ped[iChannel]);
	if (iEvent == sample) {
	  hADCvsStripBeetle1->Fill(iChannel,(float)ADC->at(iChannel));
	  hADCPedSubvsStripBeetle1->Fill(iChannel,(float)ADC->at(iChannel)-ped[iChannel]);
	}
      }
      else if ((iChannel>=NBeetle) && (iChannel<N))
      {
	hADCBeetle2->Fill((float)ADC->at(iChannel));
	hADCPedSubBeetle2->Fill((float)ADC->at(iChannel)-ped[iChannel]);
	if (iEvent == sample) {
	  hADCvsStripBeetle2->Fill(iChannel,(float)ADC->at(iChannel));
	  hADCPedSubvsStripBeetle2->Fill(iChannel,(float)ADC->at(iChannel)-ped[iChannel]);
	}
      }
      
      hADC[iChannel]->Fill((float)ADC->at(iChannel));
      hADCPedSub[iChannel]->Fill((float)ADC->at(iChannel)-ped[iChannel]);
    }
    
    EventInfoProcessed->Fill();
  }   

  DrawHist(cADCBeetle1,hADCBeetle1,"",path_to_figures);
  DrawHist(cADCPedSubBeetle1,hADCPedSubBeetle1,"",path_to_figures);

  DrawHist(cADCBeetle2,hADCBeetle2,"",path_to_figures);
  DrawHist(cADCPedSubBeetle2,hADCPedSubBeetle2,"",path_to_figures);

  DrawHist(cADCvsStripBeetle1,hADCvsStripBeetle1,"",path_to_figures);      
  DrawHist(cADCPedSubvsStripBeetle1,hADCPedSubvsStripBeetle1,"",path_to_figures);      
      
  DrawHist(cADCvsStripBeetle2,hADCvsStripBeetle2,"",path_to_figures);      
  DrawHist(cADCPedSubvsStripBeetle2,hADCPedSubvsStripBeetle2,"",path_to_figures);      

  // Write output ROOT file.
  output->Write();
  
  // Close input and output ROOT files.
  input->Close();
  output->Close();
  
  return;
}
