//************************************************
// Author: Federica Lionetto
// Created on: 08/01/2014
//************************************************

/*
   ComputeCMN reads a ROOT file (containing the raw data and the data after pedestal subtraction) and creates a ROOT file with the following information:
   - all branches in the Header tree;
   - all branches in the EventInfo tree, one per event (different folders for different CMN subtraction algorithms);
   - float CMN1 (Beetle chip 1), one per event (different folders for different CMN subtraction algorithms);
   - float CMN2 (Beetle chip 2), one per event (different folders for different CMN subtraction algorithms);
   - std::vector<float> ADCCMNSub, one per event (ADC after pedestal and CMN subtraction, different folders for different CMN subtraction algorithms);
   - several distributions, described below.

   The CMN subtraction algorithms are applied after masking the appropriate Beetle channels (cross talk from the header of the Beetle chip, strips and/or Beeetle channels shorted and/or not properly wire bonded).

   Compile with:

   make

   Run with:

   ./ComputeCMN [input ROOT file] [sensor] [additional folder]

where:
- [input ROOT file] is the complete path, including the folder and the filename, of the ROOT file one wants to process;
- [sensor] is the string identifying the sensor (UZHDaughterBoard, Hans410, Hans320, ATLAS, NoSensor);
- [additional folder] is the optional additional folder where the output will be saved.

Example of input ROOT file:
~/LHCb/UTTestBeam/AnalysisResults/CMNStudies/ProcessRawData-filename.root

Example of output ROOT file:
~/LHCb/UTTestBeam/AnalysisResults/CMNStudies/ComputeCMN-filename.root
*/

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

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

#include "../Tools/Masking.C"

#include "CMNSubMean.C"
#include "CMNSubMean2.C"
#include "CMNSubMeanOddEven.C"
#include "CMNSubMeanxStrips.C"
#include "CMNSubStraightLine.C"

void ComputeCMN(char *filename, char *sensor, char *externalPath=0);

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

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

        cout << "ComputeCMN reads a ROOT file (containing the raw data and the data after pedestal subtraction) and creates a ROOT file with the following information:" << endl;
        cout << "- all branches in the Header tree;" << endl;
        cout << "- all branches in the EventInfo tree, one per event (different folders for different CMN subtraction algorithms);" << endl;
        cout << "- float CMN1 (Beetle chip 1), one per event (different folders for different CMN subtraction algorithms);" << endl;
        cout << "- float CMN2 (Beetle chip 2), one per event (different folders for different CMN subtraction algorithms);" << endl;
        cout << "- std::vector<float> ADCCMNSub, one per event (ADC after pedestal and CMN subtraction, different folders for different CMN subtraction algorithms);" << endl;
        cout << "- several distributions, described below." << endl;

        cout << " " << endl;

        cout << "The CMN subtraction algorithms are applied after masking the appropriate Beetle channels (cross talk from the header of the Beetle chip, strips and/or Beeetle channels shorted and/or not properly wire bonded)." << endl;

        cout << " " << endl;

        cout << "Compile with:" << endl;

        cout << " " << endl;

        cout << "make" << endl;

        cout << " " << endl;

        cout << "Run with:" << endl;

        cout << " " << endl;

        cout << "./ComputeCMN [input ROOT file] [sensor] [additional folder]" << endl;

        cout << "where:" << endl;
        cout << "- [input ROOT file] is the complete path, including the folder and the filename, of the ROOT file one wants to process;" << endl;
        cout << "- [sensor] is the string identifying the sensor (UZHDaughterBoard, Hans410, Hans320, ATLAS, NoSensor);" << endl;
        cout << "- [additional folder] is the optional additional folder where the output will be saved." << endl;

        cout << "Example of input ROOT file:" << endl;
        cout << "~/LHCb/UTTestBeam/AnalysisResults/CMNStudies/ProcessRawData-filename.root" << endl;

        cout << "Example of output ROOT file:" << endl;
        cout << "~/LHCb/UTTestBeam/AnalysisResults/CMNStudies/ComputeCMN-filename.root" << endl;

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

        return 0;
    }
    else if (argc < 3)
    {
        cout << "**************************************************" << endl;

        cout << "Error! Input file missing..." << endl;
        cout << "Please use the following format:" << endl;
        cout << "./ComputeCMN [1] [2] [3]" << endl;
        cout << "with:" << endl;
        cout << "[1] = Input ROOT file, complete path;" << endl;
        cout << "[2] = Sensor (UZHDaughterBoard, Hans410, Hans320, ATLAS, NoSensor);" << endl;
        cout << "[3] = Additional folder, optional." << endl;
        cout << "Type ./ComputeCMN --info for more information." << endl;

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

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

            return 0;
        }

        return 0;  
    }
}

void ComputeCMN(char *filename, char *sensor, char *externalPath)
{
    cout << "**************************************************" << endl;
    cout << "Computing CMN..." << endl;
    cout << "**************************************************" << endl;

    // Do not comment this line.
    gROOT->ProcessLine("#include <vector>");

    // Do some fanciness to get the directory right.
    string inputDirectory = (string(filename)).substr(0,(string(filename)).find_last_of('/'));
    // string inputDirectory = "~/LHCb/UTTestBeam/AnalysisResults/CMNStudies";  
    string outputDirectory = inputDirectory;
    // string outputDirectory = "~/LHCb/UTTestBeam/AnalysisResults/CMNStudies";
    string inFilenameNoPathNoExtension = (string(filename)).substr((string(filename)).find_last_of('/')+1);
    inFilenameNoPathNoExtension = inFilenameNoPathNoExtension.substr(0,inFilenameNoPathNoExtension.find_last_of('.'));
    string outFilenameNoPathNoExtension = "ComputeCMN-"+inFilenameNoPathNoExtension.substr(inFilenameNoPathNoExtension.find_first_of('-')+1);
    if (externalPath!=0)
        outputDirectory = string(outputDirectory+"/"+externalPath);
    cout << "The input directory is: " << inputDirectory << endl;
    cout << "The output directory is: " << outputDirectory << endl;
    cout << "The name of the input ROOT file is: " << inFilenameNoPathNoExtension << endl;
    cout << "The name of the output ROOT file is: " << outFilenameNoPathNoExtension << endl;

    // Create the outputDirectory directory if it does not exist.
    string path_to_make = "mkdir -p "+outputDirectory;
    system(path_to_make.c_str());

    cout << "Figures stored in: " << outputDirectory+"/Figures/"+inFilenameNoPathNoExtension << endl;

    // Create a directory named Figures inside the directory named outputDirectory if it does not exist.
    string path_to_make_figures = "mkdir -p "+outputDirectory+"/Figures/"+inFilenameNoPathNoExtension;
    system(path_to_make_figures.c_str());

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

    string input_ROOT = filename;
    string output_ROOT = outputDirectory+"/"+outFilenameNoPathNoExtension+".root";

    // Open input ROOT file.
    cout << "Open input ROOT file: " << input_ROOT << endl;
    TFile *input = TFile::Open(TString(input_ROOT));

    // Sanity checks for input ROOT file.
    int NEvents;
    TBranch *b_NEvents = 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;
    }

    // Open output ROOT file.
    cout << "Open output ROOT file: " << output_ROOT << endl;
    TFile *output = TFile::Open(TString(output_ROOT),"RECREATE");

    // Copy the Header tree from the input to the output file.
    TTree *HeaderProcessed = Header->CloneTree(0);
    HeaderProcessed->Fill();

    // Copy the histograms with the distribution of the ADC counts of each Beetle channel (TH1F *hADC[N], before pedestal subtraction, and TH1F *hADCPedSub[N], after pedestal subtraction) from the input file to the output file.
    TH1F *hADC[N];
    TH1F *hADCPedSub[N];
    for (int iChannel=0;iChannel<N;++iChannel) {
        hADC[iChannel] = (TH1F *)input->Get(Form("hADC%d",iChannel));
        hADCPedSub[iChannel] = (TH1F *)input->Get(Form("hADCPedSub%d",iChannel));
        
        hADC[iChannel]->Write();
        hADCPedSub[iChannel]->Write();
    }

    // Close input ROOT file.
    input->Close();

    // Masking
    cout << "Masking " << filename << endl;
    Masking(string(sensor));

    // Show the distributions for one particular event.
    int sample = 1000; // Modify it.

    // Configuration of the CMNSubMean CMN subtraction algorithm.
    float th1 = 19.; // Modify it.
    float th2 = 19.; // Modify it.

    CMNSubMean(th1,th2,sample,input_ROOT,output,path_to_figures);

    // Configuration of the CMNSubMean2, CMNSubMeanOddEven, CMNSubMeanxStrips, and CMNSubStraightLine CMN subtraction algorithms.
    float factor = 3.; // Modify it.

    CMNSubMean2(factor,sample,input_ROOT,output,path_to_figures);
    CMNSubMeanOddEven(factor,sample,input_ROOT,output,path_to_figures);

    // Configuration of the CMNSubMeanxStrips CMN subtraction algorithm.
    factor = 3.;
    float x = 64.; // Modify it.

    if (x==0)
        cout << "Error! The number of Beetle channels per group is zero. The CMNSubMeanxStrips algorithm will not be executed." << endl;
    else if (NBeetle%(int)x!=0)
        cout << "Error! The number of Beetle channels per group is not a divisor of the total number of Beetle channels. The CMNSubMeanxStrips algorithm will not be executed." << endl;
    else 
        CMNSubMeanxStrips(x,factor,sample,input_ROOT,output,path_to_figures);

    factor = 2.2;
    x = 32.; // Modify it.

    if (x==0)
        cout << "Error! The number of Beetle channels per group is zero. The CMNSubMeanxStrips algorithm will not be executed." << endl;
    else if (NBeetle%(int)x!=0)
        cout << "Error! The number of Beetle channels per group is not a divisor of the total number of Beetle channels. The CMNSubMeanxStrips algorithm will not be executed." << endl;
    else 
        CMNSubMeanxStrips(x,factor,sample,input_ROOT,output,path_to_figures);

    factor = 1.5;
    x = 16.; // Modify it.

    if (x==0)
        cout << "Error! The number of Beetle channels per group is zero. The CMNSubMeanxStrips algorithm will not be executed." << endl;
    else if (NBeetle%(int)x!=0)
        cout << "Error! The number of Beetle channels per group is not a divisor of the total number of Beetle channels. The CMNSubMeanxStrips algorithm will not be executed." << endl;
    else 
        CMNSubMeanxStrips(x,factor,sample,input_ROOT,output,path_to_figures);

    factor = 3.;

    CMNSubStraightLine(factor,sample,input_ROOT,output,path_to_figures);

    output->cd();
    output->Write();
    output->Close();

    return;
}


