Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-11-03 09:36:41

0001 #include "Analyses.h"
0002 #include <array>
0003 #include <vector>
0004 #include "TROOT.h"
0005 #include <bitset>
0006 #ifdef __APPLE__
0007 #include <unistd.h>
0008 #endif
0009 #include "TF1.h"
0010 #include "TFitResult.h"
0011 #include "TFitResultPtr.h"
0012 #include "TKey.h"
0013 #include "TH1D.h"
0014 #include "TH2D.h"
0015 #include "TProfile.h"
0016 #include "TChain.h"
0017 #include "CommonHelperFunctions.h"
0018 #include "TileSpectra.h"
0019 #include "CalibSummary.h"
0020 #include "PlotHelper.h"
0021 #include "MultiCanvas.h"
0022 #include "TRandom3.h"
0023 #include "TMath.h"
0024 #include "Math/Minimizer.h"
0025 #include "Math/MinimizerOptions.h"
0026 
0027 #include "HGCROC_Convert.h"
0028 
0029 #include "waveform_fitting/waveform_fit_base.h"
0030 #include "waveform_fitting/crystal_ball_fit.h"
0031 #include "waveform_fitting/max_sample_fit.h"
0032 #include "waveform_fitting/max_sample_fit_n_integ.h"
0033 
0034 // ****************************************************************************
0035 // Checking and opening input and output files
0036 // ****************************************************************************
0037 bool Analyses::CheckAndOpenIO(void){
0038   int matchingbranch;
0039   if(!ASCIIinputName.IsNull()){
0040     std::cout << "Input to be converted into correct format :" <<  ASCIIinputName.Data() << std::endl;
0041     ASCIIinput.open(ASCIIinputName.Data(),std::ios::in);
0042     if(!ASCIIinput.is_open()){
0043       std::cout<<"Could not open input file: "<<std::endl;
0044       return false;
0045     }
0046   }
0047 
0048   //Need to check first input to get the setup...I do not think it is necessary
0049   std::cout <<"=============================================================" << std::endl;
0050   std::cout<<"Input name set to: "<<RootInputName.Data() <<std::endl;
0051   std::cout<<"Output name set to: "<<RootOutputName.Data() <<std::endl;
0052   if (!Convert) std::cout<<"Calib name set to: "<<RootCalibInputName.Data() <<std::endl;
0053   std::cout <<"=============================================================" << std::endl;
0054   if(!RootInputName.IsNull()){
0055     //File exist?
0056     RootInput=new TFile(RootInputName.Data(),"READ");
0057     if(RootInput->IsZombie()){
0058       std::cout<<"Error opening '"<<RootInputName<<"', does the file exist?"<<std::endl;
0059       return false;
0060     }
0061 
0062     //Retrieve info, start with setup, only if its not to be overwritten
0063     if (!OverWriteSetup){
0064       TsetupIn = (TTree*) RootInput->Get("Setup");
0065       if(!TsetupIn){
0066         std::cout<<"Could not retrieve the Setup tree, leaving"<<std::endl;
0067         return false;
0068       }
0069       setup=Setup::GetInstance();
0070       std::cout<<"Setup add "<<setup<<std::endl;
0071       //matchingbranch=TsetupIn->SetBranchAddress("setup",&setup);
0072       matchingbranch=TsetupIn->SetBranchAddress("setup",&rswptr);
0073       if(matchingbranch<0){
0074         std::cout<<"Error retrieving Setup info from the tree"<<std::endl;
0075         return false;
0076       }
0077       std::cout<<"Entries "<<TsetupIn->GetEntries()<<std::endl;
0078       TsetupIn->GetEntry(0);
0079       setup->Initialize(*rswptr);
0080       std::cout<<"Reading "<<RootInput->GetName()<<std::endl;
0081       std::cout<<"Setup Info "<<setup->IsInit()<<"  and  "<<setup->GetCellID(0,0)<<std::endl;
0082     }
0083 
0084     //Retrieve info, existing data?
0085     TdataIn = (TTree*) RootInput->Get("Data");
0086     if(!TdataIn){
0087       std::cout<<"Could not retrieve the Data tree, leaving"<<std::endl;
0088       return false;
0089     }
0090     matchingbranch=TdataIn->SetBranchAddress("event",&eventptr);
0091     if(matchingbranch<0){
0092       std::cout<<"Error retrieving Event info from the tree"<<std::endl;
0093       return false;
0094     }
0095     
0096     // Read calib object directly from input data file default!
0097     TcalibIn = (TTree*) RootInput->Get("Calib");
0098     if(!TcalibIn){
0099       std::cout<<"Could not retrieve Calib tree, leaving"<<std::endl;
0100       //return false;
0101     }
0102     else {
0103       matchingbranch=TcalibIn->SetBranchAddress("calib",&calibptr);
0104       if(matchingbranch<0){
0105         std::cout<<"Error retrieving calibration info from the tree"<<std::endl;
0106         TcalibIn=nullptr;
0107       }
0108       std::cout << "Retrieved calib object from input root file" << std::endl;
0109     }
0110     
0111     //All good
0112   }
0113   else if(!Convert){
0114     std::cout<<"Explicit Input option mandatory except for convertion ASCII -> ROOT"<<std::endl;
0115     return false;
0116   }  
0117   
0118   //Setup Output files
0119   if(!RootOutputName.IsNull()){    
0120     if (!Convert){
0121       TString temp = RootOutputName;
0122       temp         = temp.ReplaceAll(".root","_Hists.root");
0123       SetRootOutputHists(temp);
0124       // std::cout << "creating additional histo file: " << RootOutputNameHist.Data() << " tree in : "<< RootOutputName.Data() << std::endl;
0125     }
0126     
0127     if (!ExtractToAPhase && !IsVisualizeWaveform) {
0128       bool sCOF = CreateOutputRootFile();
0129       if (!sCOF) return false;
0130       TsetupOut = new TTree("Setup","Setup");
0131       setup=Setup::GetInstance();
0132       //TsetupOut->Branch("setup",&setup);
0133       TsetupOut->Branch("setup",&rsw);
0134       if(!NoEventTreeWrite) {
0135         TdataOut = new TTree("Data","Data");
0136         TdataOut->Branch("event",&event);
0137       }
0138       TcalibOut = new TTree("Calib","Calib");
0139       TcalibOut->Branch("calib",&calib);
0140     } else {
0141       std::cout << "No tree output needed, not creating file" << std::endl;
0142     }
0143   }
0144   else if (!SaveCalibOnly){
0145     std::cout<<"Output option mandatory except when converting"<<std::endl;
0146     return false;
0147   }
0148   
0149   if(!RootCalibInputName.IsNull()){
0150     RootCalibInput=new TFile(RootCalibInputName.Data(),"READ");
0151     if(RootCalibInput->IsZombie()){
0152       std::cout<<"Error opening '"<<RootCalibInputName<<"', does the file exist?"<<std::endl;
0153       return false;
0154     }
0155     TcalibIn = nullptr;
0156     TcalibIn = (TTree*) RootCalibInput->Get("Calib");
0157     if(!TcalibIn){
0158       std::cout<<"Could not retrieve Calib tree, leaving"<<std::endl;
0159       return false;
0160     } else {
0161       std::cout<<"Retrieved calib object from external input! " << RootCalibInputName <<std::endl;
0162     }
0163     matchingbranch=TcalibIn->SetBranchAddress("calib",&calibptr);
0164     if(matchingbranch<0){
0165       std::cout<<"Error retrieving calibration info from the tree"<<std::endl;
0166       return false;
0167     }else {
0168       std::cout<<"Correctly set branch for external calib input."<<std::endl;
0169     }
0170     
0171   }
0172 
0173   if(!RootCalibOutputName.IsNull() && SaveCalibOnly){
0174     std::cout << "entered here" << std::endl;
0175     RootCalibOutput=new TFile(RootCalibOutputName.Data(),"RECREATE");
0176     if(RootCalibOutput->IsZombie()){
0177       std::cout<<"Error opening '"<<RootCalibOutputName<<"', does the file exist?"<<std::endl;
0178       return false;
0179     }
0180     
0181     if (RootOutputName.IsNull()){
0182       TsetupOut = new TTree("Setup","Setup");
0183       setup=Setup::GetInstance();
0184       //TsetupOut->Branch("setup",&setup);
0185       TsetupOut->Branch("setup",&rsw);
0186       TcalibOut = new TTree("Calib","Calib");
0187       TcalibOut->Branch("calib",&calib);
0188     }
0189   }
0190 
0191   if(!RootPedestalInputName.IsNull()){
0192     RootPedestalInput = new TFile(RootPedestalInputName.Data(),"READ");
0193     if(RootPedestalInput->IsZombie()){
0194       std::cout<<"Error opening '"<<RootPedestalInputName<<"', does the file exist?"<<std::endl;
0195       return false;
0196     }
0197     TcalibIn = (TTree*) RootPedestalInput->Get("Calib");
0198     if(!TcalibIn){
0199       std::cout<<"Could not retrieve Calib tree, leaving"<<std::endl;
0200       return false;
0201     } else {
0202       std::cout<<"Retrieved calib object from external input for pedestals!"<<std::endl;
0203     }
0204     matchingbranch=TcalibIn->SetBranchAddress("calib",&calibptr);
0205     if(matchingbranch<0){
0206       std::cout<<"Error retrieving calibration info from the tree"<<std::endl;
0207       return false;
0208     }else {
0209       std::cout<<"Correctly set branch for external calib for pedestal input."<<std::endl;
0210     }
0211     //std::cout<<"Did the address changed? "<<&calib<<std::endl;
0212   }
0213   
0214   if(!MapInputName.IsNull()){
0215     MapInput.open(MapInputName.Data(),std::ios::in);
0216     if(!MapInput.is_open()){
0217       std::cout<<"Could not open mapping file: "<<MapInputName<<std::endl;
0218       return false;
0219     }
0220   }
0221   std::cout <<"=============================================================" << std::endl;
0222   std::cout <<" Basic setup complete" << std::endl;
0223   std::cout <<"=============================================================" << std::endl;
0224   return true;    
0225 }
0226 
0227 // ****************************************************************************
0228 // Primary process function to start all calibrations
0229 // ****************************************************************************
0230 bool Analyses::Process(void){
0231   bool status = true;
0232   ROOT::EnableImplicitMT();
0233   
0234   if(Convert){
0235     std::cout << "Converting !" << std::endl;
0236     if (HGCROC) {
0237       // Set waveform builder
0238       waveform_fit_base *waveform_builder = nullptr;
0239       // waveform_builder = new crystal_ball_fit();
0240 
0241       // // Set the parameters based off what I found in the stand alone analysis
0242       // // Alpha
0243       // waveform_builder->set_parameter(0, 1.1);  // Initial value
0244       // waveform_builder->set_parameter(10, 1);   // Lower bound
0245       // waveform_builder->set_parameter(20, 1.2); // Uppser bound
0246 
0247       // // n
0248       // waveform_builder->set_parameter(1, 0.3);
0249       // waveform_builder->set_parameter(11, 0.2);
0250       // waveform_builder->set_parameter(21, 0.6);
0251 
0252       // // x_bar
0253       // waveform_builder->set_parameter(2, 0.7);
0254       // waveform_builder->set_parameter(12, 0.5);
0255       // waveform_builder->set_parameter(22, 4.5);
0256 
0257       // // sigma
0258       // waveform_builder->set_parameter(3, 0.3);
0259       // waveform_builder->set_parameter(13, 0.25);
0260       // waveform_builder->set_parameter(23, 0.65);
0261 
0262       // // N
0263       // waveform_builder->set_parameter(4, 0);
0264       // waveform_builder->set_parameter(14, 0);
0265       // waveform_builder->set_parameter(24, 2000);
0266 
0267       // // Offset
0268       // waveform_builder->set_parameter(5, 100);  // This needs to become pedestals eventually... 
0269       // waveform_builder->set_parameter(15, 0);
0270       // waveform_builder->set_parameter(25, 160);
0271 
0272       if (GetHGCROCOptInteg() == 1 || GetHGCROCOptInteg() == 101){
0273         waveform_builder = new max_sample_fit_n_integ(GetHGCROCNSampleInteg());
0274       } else {
0275         waveform_builder = new max_sample_fit();
0276       }
0277       std::cout << "Running HGCROC conversion" << std::endl;
0278       status=run_hgcroc_conversion(this, waveform_builder);
0279       delete waveform_builder;
0280     } else {
0281       if (!(GetASCIIinputName().EndsWith(".root"))){
0282         status=ConvertASCII2Root();
0283       } else {
0284         std::cout << "WARNING: This option should only be used for the 2023 SPS test beam for which the CAEN raw data was lost!" << std::endl;
0285         status=ConvertOldRootFile2Root();
0286       }
0287     }
0288   } // end if Convert
0289   
0290   if (OverWriteSetup){
0291     status=OverWriteSetupTree();
0292     return status;
0293   }
0294   
0295   // extract pedestal from pure pedestal runs (internal triggers)
0296   if(ExtractPedestal){
0297     status=GetPedestal();
0298   }
0299   
0300   // extract pedestal from pure pedestal runs (internal triggers)
0301   if(ExtractToAPhase){
0302     status=EvaluateHGCROCToAPhases();
0303   }
0304   
0305   // copy existing calibration to other file
0306   if(ApplyTransferCalib){
0307     status=TransferCalib();
0308   }
0309 
0310   // copy existing calibration to other file
0311   if(ReextractLGHGCorr){
0312     status=ReevaluateLGHGCorr();
0313   }
0314   
0315   
0316   if (IsVisualizeWaveform){
0317     status=VisualizeWaveform();
0318   }
0319   // extract mip calibration 
0320   if(ExtractScaling){
0321     status=GetScaling();
0322   }
0323   
0324   // extract noise sample from trigger flagged files
0325   if(ReextractNoise){
0326     status=GetNoiseSampleAndRefitPedestal();
0327   }
0328   
0329   // rerun mip calibration based on triggers
0330   if (ExtractScalingImproved){
0331     status=GetImprovedScaling();
0332   }
0333   
0334   // copy full calibration to different file and calculate energy
0335   if(ApplyCalibration){
0336     status=Calibrate();
0337   }
0338   
0339   // reduce file to only noise triggers
0340   if(SaveNoiseOnly){
0341     status=SaveNoiseTriggersOnly();
0342   }
0343   
0344   // reduce file to only mip triggers
0345   if(SaveMipsOnly){
0346     status=SaveMuonTriggersOnly();
0347   }
0348   
0349   // skim HGCROC data to discard pure noise events
0350   if(SkimHGCROC){
0351     status=SkimHGCROCData();
0352   }
0353   
0354   // Evaluate local triggers and store new trigger primitives
0355   if(EvalLocalTriggers){
0356     status=RunEvalLocalTriggers();
0357   }
0358   
0359   // save calib to output only
0360   if (SaveCalibOnly){
0361     status = SaveCalibToOutputOnly();
0362   }
0363   return status;
0364 } // end Analyses::Process()
0365 
0366 // ****************************************************************************
0367 // convert original ASCII file from CAEN output to root format
0368 // ****************************************************************************
0369 bool Analyses::ConvertASCII2Root(void){
0370   //============================================
0371   //Init first
0372   //============================================
0373   // initialize setup
0374   if (MapInputName.CompareTo("")== 0) {
0375       std::cerr << "ERROR: No mapping file has been provided, please make sure you do so! Aborting!" << std::endl;
0376       return false;
0377   }
0378   std::cout << "creating mapping " << std::endl;
0379   setup->Initialize(MapInputName.Data(),debug);
0380   // initialize run number file
0381   if (RunListInputName.CompareTo("")== 0) {
0382       std::cerr << "ERROR: No run list file has been provided, please make sure you do so! Aborting!" << std::endl;
0383       return false;
0384   }
0385   std::map<int,RunInfo> ri=readRunInfosFromFile(RunListInputName.Data(),debug,0);
0386   
0387   // Clean up file headers
0388   TObjArray* tok=ASCIIinputName.Tokenize("/");
0389   // get file name
0390   TString file=((TObjString*)tok->At(tok->GetEntries()-1))->String();
0391   delete tok;
0392   tok=file.Tokenize("_");
0393   TString header=((TObjString*)tok->At(0))->String();
0394   delete tok;
0395   
0396   // Get run number from file & find necessary run infos
0397   TString RunString=header(3,header.Sizeof());
0398   std::map<int,RunInfo>::iterator it=ri.find(RunString.Atoi());
0399   //std::cout<<RunString.Atoi()<<"\t"<<it->second.species<<std::endl;
0400   event.SetRunNumber(RunString.Atoi());
0401   event.SetROtype(ReadOut::Type::Caen);
0402   event.SetBeamName(it->second.species);
0403   event.SetBeamID(it->second.pdg);
0404   event.SetBeamEnergy(it->second.energy);
0405   event.SetVop(it->second.vop);
0406   event.SetVov(it->second.vop-it->second.vbr);
0407   event.SetBeamPosX(it->second.posX);
0408   event.SetBeamPosY(it->second.posY);
0409   calib.SetRunNumber(RunString.Atoi());
0410   calib.SetVop(it->second.vop);
0411   calib.SetVov(it->second.vop-it->second.vbr);  
0412   calib.SetBCCalib(false);
0413   //============================================
0414   // Start decoding file
0415   //============================================
0416   TString aline         = "";
0417   TString versionCAEN   = "";
0418   TObjArray* tokens;
0419   std::map<int,std::vector<Caen> > tmpEvent;
0420   std::map<int,double> tmpTime;
0421   std::map<int,std::vector<Caen> >::iterator itevent;
0422   long tempEvtCounter   = 0;
0423   long writeEvtCounter  = 0;
0424   
0425   if (maxEvents != -1){
0426       std::cout << "**********************************************************************" << std::endl;
0427       std::cout << "*************************ATTENTION!************************************" << std::endl;
0428       std::cout << "Reconstruction of events will be aborted after " << maxEvents << "!" << std::endl;
0429       std::cout << "This was set manually! Make sure its what you desired!" << std::endl;
0430       std::cout << "**********************************************************************" << std::endl;
0431   }
0432   
0433   while(!ASCIIinput.eof()){                                                     // run till end of file is reached and read line by line
0434     aline.ReadLine(ASCIIinput);
0435     if(!ASCIIinput.good()) break;
0436     if(aline[0]=='/'){
0437       if (aline.Contains("File Format Version")){
0438         tokens      = aline.Tokenize(" ");
0439         versionCAEN = ((TObjString*)tokens->At(4))->String();
0440         std::cout << "File version: " << ((TObjString*)tokens->At(4))->String() << std::endl;
0441         
0442         if (!(versionCAEN.CompareTo("3.3") == 0 || versionCAEN.CompareTo("3.1") == 0)){
0443           std::cerr << "This version cannot be converted with the current code, please add the corresponding file format to the converter" << std::endl;
0444           tokens->Clear();
0445           delete tokens;
0446           return false;
0447         }  
0448         
0449         tokens->Clear();
0450         delete tokens;
0451       }
0452       else if(aline.Contains("Run start time")){
0453         tokens    = aline.Tokenize(" ");
0454         int year=((TObjString*)tokens->At(8))->String().Atoi();
0455         int month;
0456         TString Stringmonth=((TObjString*)tokens->At(5))->String();
0457         if(Stringmonth=="Jan") month=1;
0458         else if(Stringmonth=="Feb") month=2;
0459         else if(Stringmonth=="Mar") month=3;
0460         else if(Stringmonth=="Apr") month=4;
0461         else if(Stringmonth=="May") month=5;
0462         else if(Stringmonth=="Jun") month=6;
0463         else if(Stringmonth=="Jul") month=7;
0464         else if(Stringmonth=="Aug") month=8;
0465         else if(Stringmonth=="Sep") month=9;
0466         else if(Stringmonth=="Oct") month=10;
0467         else if(Stringmonth=="Nov") month=11;
0468         else if(Stringmonth=="Dec") month=12;
0469         int day=((TObjString*)tokens->At(6))->String().Atoi();
0470         int hour=((TString)((TObjString*)tokens->At(7))->String()(0,2)).Atoi();
0471         int min=((TString)((TObjString*)tokens->At(7))->String()(3,5)).Atoi();
0472         int sec=((TString)((TObjString*)tokens->At(7))->String()(6,8)).Atoi();
0473         TTimeStamp t=TTimeStamp(year,month,day,hour,min,sec);
0474         event.SetBeginRunTime(t);
0475         calib.SetBeginRunTime(t);
0476         tokens->Clear();
0477         delete tokens;
0478       }
0479       continue;
0480     }
0481     tokens=aline.Tokenize(" \t");
0482     tokens->SetOwner(true);
0483     
0484     if (versionCAEN.CompareTo("3.3") == 0){
0485       int Nfields=tokens->GetEntries();
0486       // std::cout << Nfields << std::endl;
0487       if(((TObjString*)tokens->At(0))->String()=="Brd") {
0488         tokens->Clear();
0489         delete tokens;
0490         continue;
0491       }
0492       //================================================================================
0493       // data format example
0494       // Brd  Ch       LG       HG        Tstamp_us        TrgID        NHits
0495       // 7  00       51       68     10203578.136            0      64
0496       // 7  01       55       75 
0497       //================================================================================
0498       if(Nfields!=7){
0499         std::cout<<"Unexpected number of fields"<<std::endl;
0500         std::cout<<"Expected 7, got: "<<Nfields<<", exit"<<std::endl;
0501         for(int j=0; j<Nfields;j++) std::cout<<j<<"  "<<((TObjString*)tokens->At(j))->String()<<std::endl;
0502         tokens->Clear();
0503         delete tokens;
0504         return -1;
0505       }
0506       int TriggerID=((TObjString*)tokens->At(5))->String().Atoi();
0507       int NHits=((TObjString*)tokens->At(6))->String().Atoi();
0508       double Time = ((TObjString*)tokens->At(4))->String().Atof();
0509       Caen aTile;
0510       int aBoard=((TObjString*)tokens->At(0))->String().Atoi();
0511       int achannel=((TObjString*)tokens->At(1))->String().Atoi();
0512       aTile.SetE(((TObjString*)tokens->At(3))->String().Atoi());//To Test
0513       aTile.SetADCHigh(((TObjString*)tokens->At(3))->String().Atoi());
0514       aTile.SetADCLow (((TObjString*)tokens->At(2))->String().Atoi());
0515       tokens->Clear();
0516       delete tokens;
0517       aTile.SetCellID(setup->GetCellID(aBoard,achannel));
0518       itevent=tmpEvent.find(TriggerID);
0519 
0520       if(itevent!=tmpEvent.end()){
0521         tmpTime[TriggerID]+=Time;
0522         if (aTile.GetCellID() != -1){
0523           itevent->second.push_back(aTile);
0524         } else {
0525           if(debug ==10) std::cout << "cell " << aBoard << "\t" << achannel << " wasn't active according to mapping file!" << std::endl;
0526         }
0527         for(int ich=1; ich<NHits; ich++){
0528           aline.ReadLine(ASCIIinput);
0529           tokens=aline.Tokenize(" ");
0530           tokens->SetOwner(true);
0531           Nfields=tokens->GetEntries();
0532           if(Nfields!=4){
0533             std::cout<<"Expecting 4 fields but read "<<Nfields << " at event " << tempEvtCounter <<std::endl;
0534             return -1;
0535           }
0536           achannel=((TObjString*)tokens->At(1))->String().Atoi();
0537           aTile.SetE(((TObjString*)tokens->At(3))->String().Atoi());//To Test
0538           aTile.SetADCHigh(((TObjString*)tokens->At(3))->String().Atoi());
0539           aTile.SetADCLow (((TObjString*)tokens->At(2))->String().Atoi());
0540           aTile.SetCellID(setup->GetCellID(aBoard,achannel));
0541 
0542           if (aTile.GetCellID() != -1){
0543             itevent->second.push_back(aTile);
0544           } else {
0545             if(debug ==10) std::cout << "cell " << aBoard << "\t" << achannel << " wasn't active according to mapping file!" << std::endl;
0546           }
0547           tokens->Clear();
0548           delete tokens;
0549         }
0550         // std::cout << itevent->second.size() << "\t" << setup->GetTotalNbChannels() << std::endl;
0551 
0552         if((int)itevent->second.size()==setup->GetTotalNbChannels()/*8*64*/){
0553           //Fill the tree the event is complete and erase from the map
0554           event.SetTimeStamp(tmpTime[TriggerID]/setup->GetNMaxROUnit());
0555           if(debug==1000){
0556             std::cerr<<event.GetTimeStamp()<<std::endl;
0557           }
0558           event.SetEventID(itevent->first);
0559           for(std::vector<Caen>::iterator itv=itevent->second.begin(); itv!=itevent->second.end(); ++itv){
0560             event.AddTile(new Caen(*itv));
0561           }
0562           TdataOut->Fill();
0563           writeEvtCounter++;
0564           tmpEvent.erase(itevent);
0565           tmpTime.erase(TriggerID);
0566         } 
0567       } else {
0568         //This is a new event;
0569         tempEvtCounter++;                                                                   // in crease event counts for monitoring of progress
0570         if ( maxEvents != -1 && tempEvtCounter > maxEvents){                                // abort reading of file at fixed number of events
0571           std::cout << "Manually aborted reading of file at:  " <<  maxEvents << " events" << std::endl;
0572           
0573           RootOutput->cd();
0574           // setup 
0575           RootSetupWrapper rswtmp=RootSetupWrapper(setup);
0576           rsw=rswtmp;
0577           TsetupOut->Fill();
0578           // calib
0579           TcalibOut->Fill();
0580           TcalibOut->Write();
0581           // event data
0582           TdataOut->Fill();
0583           TsetupOut->Write();
0584           TdataOut->Write();
0585           
0586           double effi = 0;
0587           if (tempEvtCounter > 0) 
0588             effi = (double)writeEvtCounter/tempEvtCounter;
0589           std::cout << "Run nr: " << event.GetRunNumber() << "\t"<< "Events written to file: " << writeEvtCounter << "\t effi: "<< effi<< std::endl;
0590           if (writeEvtCounter < 2){
0591             std::cout << "ERROR: Only " << writeEvtCounter << " events were written, something didn't go right, please check your mapping file!" << std::endl; 
0592           }
0593           TH1D* hEvents = new TH1D( "hNEvents","event category; events",  2,-0.5,1.5);
0594           hEvents->SetBinContent(1, tempEvtCounter);
0595           hEvents->SetBinContent(2, writeEvtCounter);
0596           hEvents->Write();
0597                     
0598           break;                         
0599         }
0600 
0601         if (tempEvtCounter%5000 == 0 && debug > 0) std::cout << "Converted " <<  tempEvtCounter << " events" << std::endl;
0602         // if (tempEvtCounter > 1000) continue;
0603         std::vector<Caen> vCaen;
0604         if (aTile.GetCellID() != -1){
0605           vCaen.push_back(aTile);
0606         } else {
0607           if(debug ==10) std::cout << "cell " << aBoard << "\t" << achannel << " wasn't active according to mapping file!" << std::endl;
0608         }
0609         for(int ich=1; ich<NHits; ich++){
0610           aline.ReadLine(ASCIIinput);
0611           tokens=aline.Tokenize(" ");
0612           tokens->SetOwner(true);
0613           Nfields=tokens->GetEntries();
0614           if(Nfields!=4){
0615             std::cout<<"Expecting 4 fields but read "<<Nfields<< " at event " << tempEvtCounter <<std::endl;
0616             return -1;
0617           }
0618           achannel=((TObjString*)tokens->At(1))->String().Atoi();
0619           aTile.SetE(((TObjString*)tokens->At(3))->String().Atoi());//To Test
0620           aTile.SetADCHigh(((TObjString*)tokens->At(3))->String().Atoi());
0621           aTile.SetADCLow (((TObjString*)tokens->At(2))->String().Atoi());
0622           aTile.SetCellID(setup->GetCellID(aBoard,achannel));
0623           if (aTile.GetCellID() != -1){
0624             vCaen.push_back(aTile);
0625           } else {
0626             if(debug ==10) std::cout << "cell " << aBoard << "\t" << achannel << " wasn't active according to mapping file!" << std::endl;
0627           }
0628           tokens->Clear();
0629           delete tokens;
0630         }       
0631         tmpTime[TriggerID]=Time;
0632         tmpEvent[TriggerID]=vCaen;
0633         
0634         // std::cout << vCaen.size() << "\t" << setup->GetTotalNbChannels() << std::endl;
0635         if((int)vCaen.size()==setup->GetTotalNbChannels()/*8*64*/){
0636           itevent=tmpEvent.find(TriggerID);
0637           //Fill the tree the event is complete and erase from the map
0638           event.SetTimeStamp(tmpTime[TriggerID]/setup->GetNMaxROUnit());
0639           if(debug==1000){
0640             std::cerr<<event.GetTimeStamp()<<std::endl;
0641           }
0642           event.SetEventID(itevent->first);
0643           for(std::vector<Caen>::iterator itv=vCaen.begin(); itv!=vCaen.end(); ++itv){
0644             event.AddTile(new Caen(*itv));
0645           }
0646           TdataOut->Fill();
0647           writeEvtCounter++;
0648           tmpEvent.erase(itevent);
0649           tmpTime.erase(TriggerID);
0650         } 
0651       }
0652     } else if (versionCAEN.CompareTo("3.1") == 0){
0653       int Nfields=tokens->GetEntries();
0654       if(((TObjString*)tokens->At(0))->String()=="Tstamp_us") {
0655         tokens->Clear();
0656         delete tokens;
0657         continue;
0658       }
0659       
0660       //================================================================================
0661       // data format example
0662       //   Tstamp_us        TrgID   Brd  Ch       LG       HG
0663       // 4970514.360            0    01  00       49       46 
0664       //                             01  01       49       35 
0665       //================================================================================
0666       
0667       if(Nfields!=6){
0668         std::cout<<"Unexpected number of fields"<<std::endl;
0669         std::cout<<"Expected 6, got: "<<Nfields<<", exit"<<std::endl;
0670         for(int j=0; j<Nfields;j++) std::cout<<j<<"  "<<((TObjString*)tokens->At(j))->String()<<std::endl;
0671         tokens->Clear();
0672         delete tokens;
0673         return -1;
0674       }
0675       
0676       // std::cout << aline.Data() << std::endl;
0677       int TriggerID = ((TObjString*)tokens->At(1))->String().Atoi();
0678       int NHits     = 64;                                           // temporary fix
0679       double Time   = ((TObjString*)tokens->At(0))->String().Atof();
0680       Caen aTile;
0681       int aBoard    =((TObjString*)tokens->At(2))->String().Atoi();
0682       int achannel  =((TObjString*)tokens->At(3))->String().Atoi();
0683       aTile.SetE(((TObjString*)tokens->At(5))->String().Atoi());//To Test
0684       aTile.SetADCHigh(((TObjString*)tokens->At(5))->String().Atoi());
0685       aTile.SetADCLow (((TObjString*)tokens->At(4))->String().Atoi());
0686       tokens->Clear();
0687       delete tokens;
0688       aTile.SetCellID(setup->GetCellID(aBoard,achannel));
0689       itevent=tmpEvent.find(TriggerID);
0690       
0691       if(itevent!=tmpEvent.end()){
0692         tmpTime[TriggerID]+=Time;
0693         if (aTile.GetCellID() != -1){
0694           itevent->second.push_back(aTile);
0695         } else {
0696           if(debug ==10) std::cout << "cell " << aBoard << "\t" << achannel << " wasn't active according to mapping file!" << std::endl;
0697         }
0698         for(int ich=1; ich<NHits; ich++){
0699             aline.ReadLine(ASCIIinput);
0700             // std::cout << aline.Data() << std::endl;
0701             tokens=aline.Tokenize(" ");
0702             tokens->SetOwner(true);
0703             Nfields=tokens->GetEntries();
0704             
0705             if(Nfields!=4){
0706               std::cout<< "Current line :" << aline.Data() << std::endl;
0707               std::cout<<"Expecting 4 fields but read "<<Nfields << " at event " << tempEvtCounter <<std::endl;
0708               return -1;
0709             }
0710             achannel=((TObjString*)tokens->At(1))->String().Atoi();
0711             aTile.SetE(((TObjString*)tokens->At(3))->String().Atoi());//To Test
0712             aTile.SetADCHigh(((TObjString*)tokens->At(3))->String().Atoi());
0713             aTile.SetADCLow (((TObjString*)tokens->At(2))->String().Atoi());
0714             aTile.SetCellID(setup->GetCellID(aBoard,achannel));
0715             
0716             if (aTile.GetCellID() != -1){
0717               itevent->second.push_back(aTile);
0718             } else {
0719               if(debug ==10) std::cout << "cell " << aBoard << "\t" << achannel << " wasn't active according to mapping file!" << std::endl;
0720             }
0721             tokens->Clear();
0722             delete tokens;
0723         }
0724         if((int)itevent->second.size()==setup->GetTotalNbChannels()){
0725           //Fill the tree the event is complete and erase from the map
0726           event.SetTimeStamp(tmpTime[TriggerID]/setup->GetNMaxROUnit());
0727           event.SetEventID(itevent->first);
0728           if(debug==1000){
0729             std::cerr<<event.GetTimeStamp()<<std::endl;
0730           }
0731           for(std::vector<Caen>::iterator itv=itevent->second.begin(); itv!=itevent->second.end(); ++itv){
0732             event.AddTile(new Caen(*itv));
0733           }
0734           TdataOut->Fill();
0735           writeEvtCounter++;
0736           tmpEvent.erase(itevent);
0737           tmpTime.erase(TriggerID);
0738         } else {
0739           std::cout << "didn't fill" << (int)itevent->second.size()  <<  setup->GetTotalNbChannels()<< std::endl; 
0740         }
0741       } else {
0742         //This is a new event;
0743         tempEvtCounter++;                                                                   // in crease event counts for monitoring of progress
0744         if ( maxEvents != -1 && tempEvtCounter > maxEvents){                                // abort reading of file at fixed number of events
0745           std::cout << "Manually aborted reading of file at:  " <<  maxEvents << " events" << std::endl;
0746           
0747           RootOutput->cd();
0748           // setup 
0749           RootSetupWrapper rswtmp=RootSetupWrapper(setup);
0750           rsw=rswtmp;
0751           TsetupOut->Fill();
0752           // calib
0753           TcalibOut->Fill();
0754           TcalibOut->Write();
0755           // event data
0756           TdataOut->Fill();
0757           TsetupOut->Write();
0758           TdataOut->Write();
0759           
0760           double effi = 0;
0761           if (tempEvtCounter > 0) 
0762             effi = (double)writeEvtCounter/tempEvtCounter;
0763           std::cout << "Run nr: " << event.GetRunNumber() << "\t"<< "Events written to file: " << writeEvtCounter << "\t effi: "<< effi<< std::endl;
0764           if (writeEvtCounter < 2){
0765             std::cout << "ERROR: Only " << writeEvtCounter << " events were written, something didn't go right, please check your mapping file!" << std::endl; 
0766           }
0767           TH1D* hEvents = new TH1D( "hNEvents","event category; events",  2,-0.5,1.5);
0768           hEvents->SetBinContent(1, tempEvtCounter);
0769           hEvents->SetBinContent(2, writeEvtCounter);
0770           hEvents->Write();
0771           break;                         
0772         }
0773         if (tempEvtCounter%5000 == 0 && debug > 0) std::cout << "Converted " <<  tempEvtCounter << " events" << std::endl;
0774         std::vector<Caen> vCaen;
0775         
0776         if (aTile.GetCellID() != -1){
0777           vCaen.push_back(aTile);
0778         } else {
0779           if(debug ==10) std::cout << "cell " << aBoard << "\t" << achannel << " wasn't active according to mapping file!" << std::endl;
0780         }
0781         for(int ich=1; ich<NHits; ich++){
0782           aline.ReadLine(ASCIIinput);
0783           // std::cout << aline.Data() << std::endl;
0784           tokens=aline.Tokenize(" ");
0785           tokens->SetOwner(true);
0786           Nfields=tokens->GetEntries();
0787           if(Nfields!=4){
0788             std::cout<< "Current line :" << aline.Data() << std::endl;
0789             std::cout<<"Expecting 4 fields but read "<<Nfields << " at event " << tempEvtCounter <<std::endl;
0790             return -1;
0791           }
0792           achannel=((TObjString*)tokens->At(1))->String().Atoi();
0793           aTile.SetE(((TObjString*)tokens->At(3))->String().Atoi());//To Test
0794           aTile.SetADCHigh(((TObjString*)tokens->At(3))->String().Atoi());
0795           aTile.SetADCLow (((TObjString*)tokens->At(2))->String().Atoi());
0796           aTile.SetCellID(setup->GetCellID(aBoard,achannel));
0797           if (aTile.GetCellID() != -1){
0798             vCaen.push_back(aTile);
0799           } else {
0800             if(debug ==10) std::cout << "cell " << aBoard << "\t" << achannel << " wasn't active according to mapping file!" << std::endl;
0801           }
0802           tokens->Clear();
0803           delete tokens;
0804         }
0805         tmpTime[TriggerID]=Time;
0806         tmpEvent[TriggerID]=vCaen;
0807         
0808         if((int)vCaen.size()==setup->GetTotalNbChannels()/*8*64*/){
0809           itevent=tmpEvent.find(TriggerID);
0810           //Fill the tree the event is complete and erase from the map
0811           event.SetTimeStamp(tmpTime[TriggerID]/setup->GetNMaxROUnit());
0812           if(debug==1000){
0813             std::cerr<<event.GetTimeStamp()<<std::endl;
0814           }
0815           event.SetEventID(itevent->first);
0816           for(std::vector<Caen>::iterator itv=vCaen.begin(); itv!=vCaen.end(); ++itv){
0817             event.AddTile(new Caen(*itv));
0818           }
0819           TdataOut->Fill();
0820           writeEvtCounter++;
0821           tmpEvent.erase(itevent);
0822           tmpTime.erase(TriggerID);
0823         }
0824         
0825       }      
0826     }
0827   } // finished reading in file
0828   // 
0829   
0830   
0831   if (debug > 0) std::cout << "Converted a total of " <<  tempEvtCounter << " events" << std::endl;
0832   
0833   //============================================
0834   // Fill & write all trees to output file 
0835   //============================================
0836   RootOutput->cd();
0837   // setup 
0838   RootSetupWrapper rswtmp=RootSetupWrapper(setup);
0839   rsw=rswtmp;
0840   TsetupOut->Fill();
0841   // calib
0842   TcalibOut->Fill();
0843   TcalibOut->Write();
0844   // event data
0845   TdataOut->Fill();
0846   TsetupOut->Write();
0847   TdataOut->Write();
0848 
0849   double effi = 0;
0850   if (tempEvtCounter > 0) 
0851     effi = (double)writeEvtCounter/tempEvtCounter;
0852   std::cout << "Run nr: " << event.GetRunNumber() << "\t"<< "Events written to file: " << writeEvtCounter << "\t effi: "<< effi<< std::endl;
0853   if (writeEvtCounter < 2){
0854     std::cout << "ERROR: Only " << writeEvtCounter << " events were written, something didn't go right, please check your mapping file!" << std::endl; 
0855   }
0856   TH1D* hEvents = new TH1D( "hNEvents","event category; events",  2,-0.5,1.5);
0857   hEvents->SetBinContent(1, tempEvtCounter);
0858   hEvents->SetBinContent(2, writeEvtCounter);
0859   hEvents->Write();
0860   
0861   
0862   RootOutput->Close();
0863   return true;
0864 } // end Analyses::ConvertASCII2Root()
0865 
0866 // ****************************************************************************
0867 // convert already processed root file from CAEN output to new root format
0868 // ****************************************************************************
0869 bool Analyses::ConvertOldRootFile2Root(void){
0870   //============================================
0871   //Init first
0872   //============================================
0873   // initialize setup
0874   if (MapInputName.CompareTo("")== 0) {
0875       std::cerr << "ERROR: No mapping file has been provided, please make sure you do so! Aborting!" << std::endl;
0876       return false;
0877   }
0878   setup->Initialize(MapInputName.Data(),debug);
0879   // initialize run number file
0880   if (RunListInputName.CompareTo("")== 0) {
0881       std::cerr << "ERROR: No run list file has been provided, please make sure you do so! Aborting!" << std::endl;
0882       return false;
0883   }
0884   std::map<int,RunInfo> ri=readRunInfosFromFile(RunListInputName.Data(),debug,0);
0885   
0886   // Clean up file headers
0887   TObjArray* tok=ASCIIinputName.Tokenize("/");
0888   // get file name
0889   TString file=((TObjString*)tok->At(tok->GetEntries()-1))->String();
0890   delete tok;
0891   tok=file.Tokenize("_");
0892   TString header=((TObjString*)tok->At(0))->String();
0893   delete tok;
0894   
0895   // Get run number from file & find necessary run infos
0896   TString RunString=header(3,header.Sizeof());
0897   std::map<int,RunInfo>::iterator it=ri.find(RunString.Atoi());
0898   //std::cout<<RunString.Atoi()<<"\t"<<it->second.species<<std::endl;
0899   event.SetRunNumber(RunString.Atoi());
0900   event.SetROtype(ReadOut::Type::Caen);
0901   event.SetBeamName(it->second.species);
0902   event.SetBeamID(it->second.pdg);
0903   event.SetBeamEnergy(it->second.energy);
0904   event.SetVop(it->second.vop);
0905   event.SetVov(it->second.vop-it->second.vbr);
0906   event.SetBeamPosX(it->second.posX);
0907   event.SetBeamPosY(it->second.posY);
0908   calib.SetRunNumber(RunString.Atoi());
0909   calib.SetVop(it->second.vop);
0910   calib.SetVov(it->second.vop-it->second.vbr);  
0911   calib.SetBCCalib(false);
0912     // load tree
0913   TChain *const tt_event = new TChain("tree");
0914   if (ASCIIinputName.EndsWith(".root")) {                     // are we loading a single root tree?
0915       std::cout << "loading a single root file" << std::endl;
0916       tt_event->AddFile(ASCIIinputName);
0917       TFile testFile(ASCIIinputName.Data());
0918       if (testFile.IsZombie()){
0919         std::cout << Form("The file %s is not a root file or doesn't exit, please fix the file path", ASCIIinputName.Data()) << std::endl;
0920         return false;
0921       }
0922 
0923   } else {
0924       std::cout << "please try again this isn't a root file" << std::endl;
0925   } 
0926   if(!tt_event){ std::cout << "tree not found... returning!"<< std::endl; return false;}
0927 
0928   // Define tree variables
0929   Long64_t gTrID;
0930   Double_t gTRtimeStamp;
0931   const int gMaxChannels = 64;
0932   Long64_t* gBoard          = new Long64_t[gMaxChannels];
0933   Long64_t* gChannel        = new Long64_t[gMaxChannels];
0934   Long64_t* gLG             = new Long64_t[gMaxChannels];
0935   Long64_t* gHG             = new Long64_t[gMaxChannels];
0936 
0937   if (tt_event->GetBranchStatus("t_stamp") ){
0938     tt_event->SetBranchAddress("trgid",            &gTrID);
0939     tt_event->SetBranchAddress("t_stamp",          &gTRtimeStamp);
0940     tt_event->SetBranchAddress("board",            gBoard);
0941     tt_event->SetBranchAddress("channel",          gChannel);
0942     tt_event->SetBranchAddress("LG",               gLG);
0943     tt_event->SetBranchAddress("HG",               gHG);
0944   }
0945   
0946   Long64_t nEntriesTree                 = tt_event->GetEntries();
0947   std::cout << "Number of events in tree: " << nEntriesTree << std::endl;
0948 
0949   std::map<int,std::vector<Caen> > tmpEvent;
0950   std::map<int,double> tmpTime;
0951   for (Long64_t i=0; i<nEntriesTree;i++) {
0952     // load current event
0953     tt_event->GetEntry(i);  
0954     if (i%5000 == 0 && debug > 0) std::cout << "Converted " <<  i << " events" << std::endl;    
0955     int TriggerID = gTrID;
0956     double Time   = gTRtimeStamp;
0957     std::vector<Caen> vCaen;
0958     
0959     for(Int_t ch=0; ch<gMaxChannels; ch++){   
0960       Caen aTile;
0961       int aBoard      = gBoard[ch];
0962       int achannel    = gChannel[ch];
0963       aTile.SetE(gHG[ch]);//To Test
0964       aTile.SetADCHigh(gHG[ch]);
0965       aTile.SetADCLow (gLG[ch]);
0966       aTile.SetCellID(setup->GetCellID(aBoard,achannel));
0967       if (aTile.GetCellID() != -1){
0968         vCaen.push_back(aTile);
0969       } else {
0970         if(debug ==10) std::cout << "cell " << aBoard << "\t" << achannel << " wasn't active according to mapping file!" << std::endl;
0971       }
0972     }
0973     
0974      if((int)vCaen.size()==setup->GetTotalNbChannels()){
0975       //Fill the tree the event is complete and erase from the map
0976       event.SetTimeStamp(Time);
0977       if(debug==1000){
0978             std::cerr<<event.GetTimeStamp()<<std::endl;
0979       }
0980       event.SetEventID(TriggerID);
0981       for(std::vector<Caen>::iterator itv=vCaen.begin(); itv!=vCaen.end(); ++itv){
0982         event.AddTile(new Caen(*itv));
0983       }
0984       TdataOut->Fill();
0985       vCaen.clear();
0986     }
0987   } // finished reading the file
0988 
0989   // 
0990   if (debug > 0) std::cout << "Converted a total of " <<  nEntriesTree << " events" << std::endl;
0991   
0992   //============================================
0993   // Fill & write all trees to output file 
0994   //============================================
0995   RootOutput->cd();
0996   // setup 
0997   RootSetupWrapper rswtmp=RootSetupWrapper(setup);
0998   rsw=rswtmp;
0999   TsetupOut->Fill();
1000   // calib
1001   TcalibOut->Fill();
1002   TcalibOut->Write();
1003   // event data
1004   TdataOut->Fill();
1005   TsetupOut->Write();
1006   TdataOut->Write();
1007 
1008   RootOutput->Close();
1009   return true;
1010 } // end Analyses::ConvertOldRootFile2Root()
1011 
1012 // ****************************************************************************
1013 // extract pedestral from dedicated data run, no other data in run 
1014 // ****************************************************************************
1015 bool Analyses::GetPedestal(void){
1016   std::cout<<"GetPedestal for maximium "<< setup->GetMaxCellID() << " cells" <<std::endl;
1017     
1018   // Event loop to fill histograms & output tree
1019   std::cout << "N max layers: " << setup->GetNMaxLayer() << "\t columns: " <<  setup->GetNMaxColumn() << "\t row: " << setup->GetNMaxRow() << "\t module: " <<  setup->GetNMaxModule() << std::endl;
1020   if(TcalibIn) TcalibIn->GetEntry(0);
1021   // check whether calib should be overwritten based on external text file
1022   if (OverWriteCalib){
1023     calib.ReadCalibFromTextFile(ExternalCalibFile,debug);
1024   }
1025   
1026   int evts=TdataIn->GetEntries();
1027   TdataIn->GetEntry(0);
1028   int runNr             = event.GetRunNumber();
1029   ReadOut::Type typeRO  = event.GetROtype();
1030   if (maxEvents == -1){
1031     maxEvents = evts;
1032   } else {
1033     std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
1034     std::cout << "ATTENTION: YOU ARE RESETTING THE MAXIMUM NUMBER OF EVENTS TO BE PROCESSED TO: " << maxEvents << ". THIS SHOULD ONLY BE USED FOR TESTING!" << std::endl;
1035     std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
1036   }
1037   std::cout<< "original run numbers calib: "<<calib.GetRunNumber() << "\t" << calib.GetRunNumberPed() << "\t" << calib.GetRunNumberMip() << std::endl;
1038   calib.SetRunNumberPed(runNr);
1039   calib.SetBeginRunTimePed(event.GetBeginRunTimeAlt());
1040   std::cout<< "reset run numbers calib: "<< calib.GetRunNumber() << "\t" << calib.GetRunNumberPed() << "\t" << calib.GetRunNumberMip() << std::endl;
1041 
1042   // Get run info object
1043   std::map<int,RunInfo> ri=readRunInfosFromFile(RunListInputName.Data(),debug,0);
1044   std::map<int,RunInfo>::iterator it=ri.find(runNr);
1045   // Find detector config 
1046   DetConf::Type detConf = setup->GetDetectorConfig();
1047   if (it->second.detector == "FoCal-H")
1048     detConf = DetConf::Type::FocalH; 
1049   std::cout << "DETECTOR config: " << detConf << std::endl; 
1050   
1051   int maxChannelPerLayer          = (setup->GetNMaxColumn()+1)*(setup->GetNMaxRow()+1)*(setup->GetNMaxModule()+1);
1052   int maxChannelPerLayerSingleMod = (setup->GetNMaxColumn()+1)*(setup->GetNMaxRow()+1);
1053   ROOT::Math::MinimizerOptions::SetDefaultMinimizer("Minuit2", "Migrad");  
1054   
1055   // create HG and LG histo's per channel
1056   TH2D* hspectraHGvsCellID      = new TH2D( "hspectraHG_vsCellID","ADC spectrum High Gain vs CellID; cell ID; ADC_{HG} (arb. units) ",
1057                                             setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5, 4000,0,4000);
1058   hspectraHGvsCellID->SetDirectory(0);
1059   TH2D* hspectraLGvsCellID      = new TH2D( "hspectraLG_vsCellID","ADC spectrum Low Gain vs CellID; cell ID; ADC_{LG} (arb. units)  ",
1060                                             setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5, 4000,0,4000);
1061   hspectraLGvsCellID->SetDirectory(0);
1062   TH1D* hMeanPedHGvsCellID      = new TH1D( "hMeanPedHG_vsCellID","mean Ped High Gain vs CellID ; cell ID; #mu_{noise, HG} (arb. units) ",
1063                                             setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5);
1064   hMeanPedHGvsCellID->SetDirectory(0);
1065   TH2D* hspectraHGMeanVsLayer   = new TH2D( "hspectraHGMeanVsLayer","Mean Ped High Gain vs CellID; layer; brd channel; #mu_{Ped HG} (arb. units) ",
1066                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
1067   hspectraHGMeanVsLayer->SetDirectory(0);
1068   TH2D* hspectraHGSigmaVsLayer  = new TH2D( "hspectraHGSigmaVsLayer","Mean Ped High Gain vs CellID; layer; brd channel; #sigma_{Ped HG} (arb. units) ",
1069                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
1070   hspectraHGSigmaVsLayer->SetDirectory(0);
1071   TH1D* hMeanPedLGvsCellID      = new TH1D( "hMeanPedLG_vsCellID","mean Ped Low Gain vs CellID ; cell ID; #mu_{noise, LG} (arb. units) ",
1072                                             setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5);
1073   hMeanPedLGvsCellID->SetDirectory(0);
1074   TH2D* hspectraLGMeanVsLayer   = new TH2D( "hspectraLGMeanVsLayer","Mean Ped Low Gain vs CellID; layer; brd channel; #mu_{PED LG} (arb. units) ",
1075                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
1076   hspectraLGMeanVsLayer->SetDirectory(0);
1077   TH2D* hspectraLGSigmaVsLayer  = new TH2D( "hspectraLGSigmaVsLayer","Mean Ped Low Gain vs CellID; layer; brd channel; #sigma_{Ped LG} (arb. units)",
1078                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
1079   hspectraLGSigmaVsLayer->SetDirectory(0);
1080 
1081   TH2D* hPedMeanHGvsLG          = new TH2D( "hPedMeanHGvsLG","Mean Ped High Gain vs Low Gain; #mu_{noise, HG} (arb. units); #mu_{noise, LG} (arb. units)", 500, 0, 250, 500, 0, 250);
1082   hPedMeanHGvsLG->SetDirectory(0);
1083   
1084   if (typeRO == ReadOut::Type::Caen) 
1085     std::cout << "Read-out type CAEN" << std::endl;
1086   else{
1087     std::cout << "Read-out type HGCROC" << std::endl;
1088     hPedMeanHGvsLG->GetYaxis()->SetTitle("#mu_{noise, wave} (arb. units)");
1089     hPedMeanHGvsLG->GetXaxis()->SetTitle("#mu_{noise, 0th sample} (arb. units)");
1090     hPedMeanHGvsLG->SetTitle("Pedestal Eval 0th sample vs wave");
1091     hspectraLGvsCellID->SetYTitle("ADC (arb. units) all samples");
1092   }
1093 
1094   
1095   std::map<int,TileSpectra> hSpectra;
1096   std::map<int, TileSpectra>::iterator ithSpectra;  
1097 
1098   // create output file for histos
1099   if (!CreateOutputRootHistFile()) return false;
1100   // entering histoOutput file
1101   RootOutputHist->mkdir("IndividualCells");
1102   RootOutputHist->cd("IndividualCells");
1103 
1104   RootOutput->cd();
1105   
1106   
1107   for(int i=0; i<evts && i < maxEvents; i++){
1108     TdataIn->GetEntry(i);
1109     if (i%5000 == 0&& i > 0 && debug > 0) std::cout << "Reading " <<  i << "/" << evts << " events"<< std::endl;
1110     for(int j=0; j<event.GetNTiles(); j++){
1111       if (typeRO == ReadOut::Type::Caen) {
1112         Caen* aTile=(Caen*)event.GetTile(j);
1113         if (i == 0 && debug > 2){
1114           std::cout << ((TString)setup->DecodeCellID(aTile->GetCellID())).Data() << std::endl;
1115         }
1116         ithSpectra=hSpectra.find(aTile->GetCellID());
1117         if(ithSpectra!=hSpectra.end()){
1118           ithSpectra->second.FillCAEN(aTile->GetADCLow(),aTile->GetADCHigh());
1119         } else {
1120           RootOutputHist->cd("IndividualCells");
1121           hSpectra[aTile->GetCellID()]=TileSpectra("1stExtraction",aTile->GetCellID(),calib.GetTileCalib(aTile->GetCellID()), event.GetROtype(), nSampleHGCROCInt, debug);
1122           hSpectra[aTile->GetCellID()].FillCAEN(aTile->GetADCLow(),aTile->GetADCHigh());
1123           RootOutput->cd();
1124         }
1125         hspectraHGvsCellID->Fill(aTile->GetCellID(), aTile->GetADCHigh());
1126         hspectraLGvsCellID->Fill(aTile->GetCellID(), aTile->GetADCLow());
1127       }
1128       else if (typeRO == ReadOut::Type::Hgcroc){ // Process HGCROC Data
1129         Hgcroc* aTile=(Hgcroc*)event.GetTile(j);
1130         if (i == 0 && debug == 3 ){
1131           std::cout << ((TString)setup->DecodeCellID(aTile->GetCellID())).Data() << std::endl;
1132         }
1133         // if (debug > 3 && aTile->GetCellID() == 2 ){
1134           // std::bitset<10> pedBit(aTile->GetPedestal());
1135           // std::bitset<5> pedBit5bit(aTile->GetPedestal());
1136           // std::cout << aTile->GetPedestal() << "\t" << pedBit << "\t" << pedBit5bit << std::endl;
1137         // }
1138         
1139         // single tile debug info print
1140         if (debug > 10 ){
1141           aTile->PrintWaveFormDebugInfo(aTile->GetPedestal(), aTile->GetPedestal(), 1);
1142         }
1143         
1144         ithSpectra=hSpectra.find(aTile->GetCellID());
1145         if(ithSpectra!=hSpectra.end()){
1146           // Get the tile spectra if it already exists
1147           ithSpectra->second.FillExtHGCROCPed(aTile->GetADCWaveform(),aTile->GetPedestal());
1148         } else {
1149           // Make a new tile spectra if it isn't found
1150           RootOutputHist->cd("IndividualCells");
1151           hSpectra[aTile->GetCellID()]= TileSpectra("1stExtraction", 4, aTile->GetCellID(), calib.GetTileCalib(aTile->GetCellID()), event.GetROtype(), nSampleHGCROCInt, debug);
1152           hSpectra[aTile->GetCellID()].FillExtHGCROCPed(aTile->GetADCWaveform(),aTile->GetPedestal());
1153           RootOutput->cd();
1154         }
1155         // std::cout << "Cell ID: " << aTile->GetCellID() << ", Tile E: " << aTile->GetPedestal() << std::endl;
1156         hspectraHGvsCellID->Fill(aTile->GetCellID(), aTile->GetPedestal());
1157         for (int k = 0; k < (int)(aTile->GetADCWaveform()).size(); k++ ){
1158           hspectraLGvsCellID->Fill(aTile->GetCellID(),aTile->GetADCWaveform().at(k));
1159         }
1160       }
1161     }
1162     RootOutput->cd();
1163     TdataOut->Fill();
1164   }
1165   
1166   //==================================================================================
1167   // fit pedestal
1168   //==================================================================================
1169   double* parameters=new double[8];
1170   bool isGood  = true;
1171   bool isGood2 = true;
1172 
1173   for(ithSpectra=hSpectra.begin(); ithSpectra!=hSpectra.end(); ++ithSpectra){
1174     if ( debug > 2) std::cout << ((TString)setup->DecodeCellID(ithSpectra->second.GetCellID())).Data() << std::endl;
1175     // std::cerr << "Fitting noise for cell ID: " << ithSpectra->second.GetCellID() << std::endl;
1176     isGood=ithSpectra->second.FitNoise(parameters, yearData, false);
1177     if (!isGood && !(typeRO == ReadOut::Type::Hgcroc)) {
1178       std::cerr << "Noise fit failed for cell ID: " << ithSpectra->second.GetCellID() << std::endl;
1179       continue;
1180     }
1181 
1182     if (typeRO == ReadOut::Type::Hgcroc){
1183       isGood2=ithSpectra->second.FitPedConstWave(debug);
1184 
1185       if (!isGood && !isGood2) {
1186         std::cerr << "both noise fits failed " << ithSpectra->second.GetCellID() << std::endl;
1187         continue;
1188       } else {
1189         if (!isGood2) std::cerr << "Noise-wave form fit failed for cell ID: " << ithSpectra->second.GetCellID() << std::endl;
1190         if (!isGood){
1191           std::cerr << "1D Noise fit failed for cell ID: " << ithSpectra->second.GetCellID() << std::endl;
1192           parameters[4] = -1;
1193           parameters[5] = -1;
1194           parameters[6] = -1;
1195           parameters[7] = -1;
1196         }
1197       }
1198     }
1199     int cellID    = ithSpectra->second.GetCellID();
1200     int layer     = setup->GetLayer(cellID);
1201     int chInLayer = setup->GetChannelInLayerFull(cellID, detConf);
1202     
1203     
1204     
1205     hMeanPedHGvsCellID->SetBinContent(hMeanPedHGvsCellID->FindBin(cellID), parameters[4]);
1206     hMeanPedHGvsCellID->SetBinError  (hMeanPedHGvsCellID->FindBin(cellID), parameters[6]);
1207     hspectraHGMeanVsLayer->SetBinContent(hspectraHGMeanVsLayer->FindBin(layer,chInLayer), parameters[4]);
1208     hspectraHGMeanVsLayer->SetBinError(hspectraHGMeanVsLayer->FindBin(layer,chInLayer), parameters[5]);
1209     hspectraHGSigmaVsLayer->SetBinContent(hspectraHGSigmaVsLayer->FindBin(layer,chInLayer), parameters[6]);
1210     hspectraHGSigmaVsLayer->SetBinError(hspectraHGSigmaVsLayer->FindBin(layer,chInLayer), parameters[7]);
1211     if (typeRO == ReadOut::Type::Caen){
1212       hMeanPedLGvsCellID->SetBinContent(hMeanPedLGvsCellID->FindBin(cellID), parameters[0]);
1213       hMeanPedLGvsCellID->SetBinError  (hMeanPedLGvsCellID->FindBin(cellID), parameters[2]);
1214       hspectraLGMeanVsLayer->SetBinContent(hspectraLGMeanVsLayer->FindBin(layer,chInLayer), parameters[0]);
1215       hspectraLGMeanVsLayer->SetBinError(hspectraLGMeanVsLayer->FindBin(layer,chInLayer), parameters[1]);
1216       hspectraLGSigmaVsLayer->SetBinContent(hspectraLGSigmaVsLayer->FindBin(layer,chInLayer), parameters[2]);
1217       hspectraLGSigmaVsLayer->SetBinError(hspectraLGSigmaVsLayer->FindBin(layer,chInLayer), parameters[3]);
1218       
1219       hPedMeanHGvsLG->Fill(parameters[4],parameters[0]);
1220     } else if (isGood2 && typeRO == ReadOut::Type::Hgcroc){
1221       hMeanPedLGvsCellID->SetBinContent(hMeanPedLGvsCellID->FindBin(cellID), calib.GetPedestalMeanL(cellID));
1222       hMeanPedLGvsCellID->SetBinError  (hMeanPedLGvsCellID->FindBin(cellID), calib.GetPedestalSigL(cellID));
1223       hspectraLGMeanVsLayer->SetBinContent(hspectraLGMeanVsLayer->FindBin(layer,chInLayer), calib.GetPedestalMeanL(cellID));
1224       hspectraLGMeanVsLayer->SetBinError(hspectraLGMeanVsLayer->FindBin(layer,chInLayer), calib.GetPedestalSigL(cellID));
1225       
1226       hPedMeanHGvsLG->Fill(parameters[4],calib.GetPedestalMeanL(cellID));
1227     }
1228   }
1229 
1230   //==================================================================================
1231   // Write Root Files with pure data tree & histo output
1232   //==================================================================================
1233   //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1234   // Write tree output
1235   //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1236   RootOutput->cd();
1237   // write output tree (copy of raw data)
1238   TdataOut->Write();
1239   // write setup tree (copy of raw data)
1240   TsetupIn->CloneTree()->Write();
1241   if (IsCalibSaveToFile()){
1242     TString fileCalibPrint = RootOutputName;
1243     fileCalibPrint         = fileCalibPrint.ReplaceAll(".root","_calib.txt");
1244     calib.PrintCalibToFile(fileCalibPrint);
1245   }
1246   // fill calib tree & write it  
1247   TcalibOut->Fill();
1248   TcalibOut->Write();
1249   // close open root output file
1250   RootOutput->Write();
1251   RootOutput->Close();
1252   
1253   //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1254   // Write histoOutput file
1255   //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1256   RootOutputHist->cd("IndividualCells");
1257   for(ithSpectra=hSpectra.begin(); ithSpectra!=hSpectra.end(); ++ithSpectra){
1258     ithSpectra->second.Write(true);
1259   }
1260   RootOutputHist->cd();
1261   hspectraHGvsCellID->Write();
1262   hMeanPedHGvsCellID->Write();
1263   hspectraHGMeanVsLayer->Write();
1264   hspectraHGSigmaVsLayer->Write();
1265   hPedMeanHGvsLG->Write();
1266   if (typeRO == ReadOut::Type::Caen){
1267     hspectraLGvsCellID->Write();
1268     hMeanPedLGvsCellID->Write();
1269     hspectraLGMeanVsLayer->Write();
1270     hspectraLGSigmaVsLayer->Write();
1271   } else {
1272     hspectraLGvsCellID->Write("hAllADC_vsCellID");
1273     hMeanPedLGvsCellID->GetYaxis()->SetTitle("#mu_{Ped ADC, wave} (arb. units)");
1274     hMeanPedLGvsCellID->Write("hMeanPedWave_vsCellID");
1275     hspectraLGMeanVsLayer->GetZaxis()->SetTitle("#mu_{Ped ADC, wave} (arb. units)");
1276     hspectraLGMeanVsLayer->Write("hspectraPedWaveMeanVsLayer");
1277   }
1278   // close open root hist output file
1279   RootOutputHist->Write();
1280   RootOutputHist->Close();
1281   // close open input root file
1282   RootInput->Close();
1283 
1284   
1285   //==================================================================================
1286   // Plotting 
1287   //==================================================================================  
1288   // create directory for plot output
1289   TString outputDirPlots = GetPlotOutputDir();
1290   gSystem->Exec("mkdir -p "+outputDirPlots);
1291   // general variable setup 
1292   double averagePedMeanHG = calib.GetAveragePedestalMeanHigh();
1293   double averagePedSigHG  = calib.GetAveragePedestalSigHigh();
1294   double averagePedMeanLG = calib.GetAveragePedestalMeanLow();
1295   double averagePedSigLG  = calib.GetAveragePedestalSigLow();
1296 
1297   //**********************************************************************
1298   // Create canvases for channel overview plotting
1299   //**********************************************************************
1300   Double_t textSizeRel = 0.035;
1301   StyleSettingsBasics("pdf");
1302   SetPlotStyle();
1303   
1304   TCanvas* canvas2DCorr = new TCanvas("canvasCorrPlots","",0,0,1450,1200);  // gives the page size
1305   DefaultCanvasSettings( canvas2DCorr, 0.08, 0.13, 0.045, 0.07);
1306   canvas2DCorr->SetLogz();
1307   
1308   // overview all spectra CAEN HG / HGCROC 0th sample ADC 
1309   if (typeRO == ReadOut::Type::Hgcroc) hspectraHGvsCellID->GetYaxis()->SetTitle("Pedestal ADC (arb units)");
1310   PlotSimple2D( canvas2DCorr, hspectraHGvsCellID, 300, setup->GetMaxCellID()+1, textSizeRel, Form("%s/HG_Noise.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 5, kFALSE, "colz", true);
1311   
1312   // overview all spectra CAEN LG / HGCROC all sample ADC 
1313   if (typeRO == ReadOut::Type::Caen){
1314     PlotSimple2D( canvas2DCorr, hspectraLGvsCellID, 300, setup->GetMaxCellID()+1, textSizeRel, Form("%s/LG_Noise.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 5, kFALSE, "colz", true);
1315   } else {
1316     PlotSimple2D( canvas2DCorr, hspectraLGvsCellID, 300, setup->GetMaxCellID()+1, textSizeRel, Form("%s/AllSampleADC.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 5, kFALSE, "colz", true);
1317   }
1318   
1319   canvas2DCorr->SetLogz(0);
1320   // overview all pedestal means CAEN HG / HGCROC 0th sample ADC 
1321   PlotSimple2D( canvas2DCorr, hspectraHGMeanVsLayer, -10000, -10000, textSizeRel, Form("%s/HG_NoiseMean.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 5, kFALSE, "colz", true, Form("#LT#mu_{HG}#GT = %2.2f", averagePedMeanHG));
1322   // overview all pedestal width CAEN HG / HGCROC 0th sample ADC 
1323   PlotSimple2D( canvas2DCorr, hspectraHGSigmaVsLayer,-10000, -10000, textSizeRel, Form("%s/HG_NoiseSigma.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 5,  kFALSE, "colz", true, Form("#LT#sigma_{HG}#GT = %2.2f", averagePedSigHG));
1324   // overview all correlation different pedestal means
1325   PlotSimple2D( canvas2DCorr, hPedMeanHGvsLG, -10000, -10000, textSizeRel, Form("%s/PedMean_HG_LG.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 5, kFALSE, "colz", true, "");
1326 
1327   if (typeRO == ReadOut::Type::Caen){
1328     // overview all pedestal means CAEN LG 
1329     PlotSimple2D( canvas2DCorr, hspectraLGMeanVsLayer, -10000, -10000, textSizeRel, Form("%s/LG_NoiseMean.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 5, kFALSE, "colz", true, Form("#LT#mu_{LG}#GT = %2.2f", averagePedMeanLG));
1330     // overview all pedestal width CAEN LG 
1331     PlotSimple2D( canvas2DCorr, hspectraLGSigmaVsLayer, -10000, -10000, textSizeRel, Form("%s/LG_NoiseSigma.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 5, kFALSE, "colz", true, Form("#LT#sigma_{LG}#GT = %2.2f", averagePedSigLG));
1332   } else {
1333     // overview all pedestal means HGCROC waveform fit
1334     PlotSimple2D( canvas2DCorr, hspectraLGMeanVsLayer, -10000, -10000, textSizeRel, Form("%s/PedWave_NoiseMean.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 5, kFALSE, "colz", true, Form("#LT#mu_{wave}#GT = %2.2f", averagePedMeanLG));
1335   }
1336   
1337   // *********************************************************************************************************
1338   // Set up ranges for multipanel plotting
1339   // *********************************************************************************************************
1340   Int_t textSizePixel = 30;
1341   double minADCRange = 0; 
1342   double maxADCRange = 275;
1343   if( typeRO == ReadOut::Type::Hgcroc ){
1344     minADCRange = 50; 
1345     maxADCRange = 150;
1346   }
1347   //***********************************************************************************************************
1348   // do single layer plotting
1349   //***********************************************************************************************************
1350   MultiCanvas panelPlot(detConf, "Pedestal");
1351   bool init1D = panelPlot.Initialize(1);
1352   MultiCanvas panelPlot2D(detConf, "Pedestal2D");
1353   bool init2D = panelPlot2D.Initialize(2);
1354   
1355   panelPlot.PlotNoiseWithFits(hSpectra, 0, minADCRange, maxADCRange, 1.2, 
1356                               Form("%s/Noise_HG",outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, skipPlotLayer );
1357   if (typeRO == ReadOut::Type::Caen){
1358     panelPlot.PlotNoiseWithFits(hSpectra, 1, minADCRange, maxADCRange, 1.2, 
1359                               Form("%s/Noise_LG",outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, skipPlotLayer);    
1360   } else if (typeRO == ReadOut::Type::Hgcroc){
1361     panelPlot.PlotNoiseWithFits(hSpectra, 1, minADCRange, maxADCRange, 1.2, 
1362                               Form("%s/AllSampleADC",outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, skipPlotLayer );
1363     panelPlot2D.PlotCorr2DLayer(hSpectra, 1, 0, it->second.samples+1, 0, 300, 
1364                                 Form("%s/Waveform",outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, 0, -1, skipPlotLayer );
1365   }
1366   
1367   return true;
1368 } // end Analyses::GetPedestal()
1369 
1370 // ****************************************************************************
1371 // extract toA offset from data runs
1372 // ideally a run with lots of amplitude should be used (i.e. hadrons)
1373 // ****************************************************************************
1374 bool Analyses::EvaluateHGCROCToAPhases(void){
1375   
1376   std::cout<<"Evaluate HGCROC ToA Phases"<<std::endl;
1377   int evts=TdataIn->GetEntries();
1378 
1379   // initialize calib
1380   TcalibIn->GetEntry(0);        // use first calib object in list (there might be more)
1381   
1382   // initialize lookup-table run list
1383   std::map<int,RunInfo> ri=readRunInfosFromFile(RunListInputName.Data(),debug,0);
1384   
1385   // intialize run infos & reset calib object to correct run number
1386   TdataIn->GetEntry(0);     // use first event to get infos
1387   Int_t runNr = event.GetRunNumber();
1388   ReadOut::Type typeRO  = event.GetROtype();
1389   std::cout<< "original run numbers calib: "<<calib.GetRunNumber() << "\t" << calib.GetRunNumberPed() << "\t" << calib.GetRunNumberMip() << std::endl;
1390   calib.SetRunNumber(runNr);
1391   calib.SetBeginRunTime(event.GetBeginRunTimeAlt());
1392   std::cout<< "reset run numbers calib: "<< calib.GetRunNumber() << "\t" << calib.GetRunNumberPed() << "\t" << calib.GetRunNumberMip() << std::endl;
1393   
1394   // Get run info object
1395   std::map<int,RunInfo>::iterator it=ri.find(runNr);
1396   
1397   // No need to event attempt to run on CAEN data
1398   if (typeRO == ReadOut::Type::Caen){
1399     std::cout <<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
1400     std::cout << "ATTENTION this function isn't meant to run on data collected with the CAEN DT5202!\n ABORTING!" << std::endl;
1401     std::cout <<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
1402     return false; 
1403   }
1404   
1405   // check whether calib should be overwritten based on external text file
1406   if (OverWriteCalib){
1407     calib.ReadCalibFromTextFile(ExternalCalibFile,debug);
1408   }  
1409   
1410   Int_t minNSampleToA = 2;
1411   //==================================================================================
1412   // create additional output hist
1413   //==================================================================================
1414   if (!CreateOutputRootHistFile()) return false;
1415   RootOutputHist->cd();
1416 
1417   TH2D* hSampleTOAVsCellID       = new TH2D( "hSampleTOAvsCellID","#sample ToA; cell ID; #sample TOA",
1418                                             setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5, it->second.samples,0,it->second.samples);
1419   hSampleTOAVsCellID->SetDirectory(0);
1420 
1421   TH2D* hTOANsVsCellID       = new TH2D( "hTOANsVsCellID","ToA (ns); cell ID; ToA (ns)",
1422                                             setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5, 500,-250,0);
1423   hTOANsVsCellID->SetDirectory(0);
1424   TH2D* hSampleMaxADCVsCellID       = new TH2D( "hSampleMaxADCvsCellID","#sample ToA; cell ID; #sample Max ADC",
1425                                             setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5, it->second.samples,0,it->second.samples);
1426   hSampleMaxADCVsCellID->SetDirectory(0);
1427 
1428   TH1D* hSampleTOA               = new TH1D( "hSampleTOA","#sample ToA; #sample TOA",
1429                                               it->second.samples,0,it->second.samples);
1430   hSampleTOA->SetDirectory(0);
1431   TH1D* hSampleMaxADC            = new TH1D( "hSampleMaxADC","#sample ToA; #sample maxADC",
1432                                               it->second.samples,0,it->second.samples);
1433   hSampleMaxADC->SetDirectory(0);
1434   TH1D* hSampleAboveTh           = new TH1D( "hSampleAboveTh","#sample ToA; #sample above th",
1435                                               it->second.samples,0,it->second.samples);
1436   hSampleAboveTh->SetDirectory(0);
1437   TH1D* hSampleDiff              = new TH1D( "hSampleDiff","#sample ToA-#sample Max ADC; #sample maxADC-#sampleMax ADC",
1438                                               8,-0.5,7.5);
1439   hSampleDiff->SetDirectory(0);
1440   TH1D* hSampleDiffMin           = new TH1D( "hSampleDiffMin","#sample ToA-#sample above th; #sample maxADC-#sample  above th",
1441                                               8,-0.5,7.5);
1442   hSampleDiffMin->SetDirectory(0);
1443   
1444   std::vector<std::array<std::array<TH2D*, 5>, 2>> h2DToAvsADC(setup->GetNMaxROUnit()+1);
1445   std::vector<std::array<std::array<TProfile*, 5>, 2>> hToAvsADC(setup->GetNMaxROUnit()+1);
1446   std::vector<std::array<std::array<TH2D*, 5>, 2>> h2DWaveFormHalfAsic(setup->GetNMaxROUnit()+1);
1447   std::vector<std::array<std::array<TProfile*, 5>, 2>> hWaveFormHalfAsic(setup->GetNMaxROUnit()+1);
1448   std::vector<std::array<TH2D*, 2>> h2DToAvsnSample(setup->GetNMaxROUnit()+1);
1449 
1450   std::vector<std::array<TH2D*, 2>> h2DWaveFormHalfAsicAll(setup->GetNMaxROUnit()+1);
1451   std::vector<std::array<TProfile*, 2>> hWaveFormHalfAsicAll(setup->GetNMaxROUnit()+1);
1452   
1453   for (Int_t ro = 0; ro < setup->GetNMaxROUnit()+1; ro++){
1454     for (int h = 0; h< 2; h++){
1455       h2DToAvsnSample[ro][h]    = new TH2D(Form("h2DTOASample_Asic_%d_Half_%d",ro,h),
1456                                             Form("Sample vs TOA %d %d; TOA (arb. units); #sample",ro,h), 1024/8,0,1024,it->second.samples,0,it->second.samples);
1457       hWaveFormHalfAsicAll[ro][h]    = new TProfile(Form("WaveForm_Asic_%d_Half_%d",ro,h),
1458                                         Form("ADC-TOA correlation %d %d;  t (ns) ; ADC (arb. units)",ro,h),550,-50,500);
1459       h2DWaveFormHalfAsicAll[ro][h]  = new TH2D(Form("h2DWaveForm_Asic_%d_Half_%d",ro,h),
1460                                         Form("2D ADC vs TOA %d %d;  t (ns) ; ADC (arb. units)",ro,h), 
1461                                         550,-50,500, 1044/4, -20, 1024);
1462       h2DToAvsnSample[ro][h]->SetDirectory(0);
1463       hWaveFormHalfAsicAll[ro][h]->SetDirectory(0);
1464       h2DWaveFormHalfAsicAll[ro][h]->SetDirectory(0);
1465       
1466       for (int p = 0; p< 5; p++){
1467         hToAvsADC[ro][h][p]    = new TProfile(Form("ADCTOA_Asic_%d_Half_%d_NToASample_%d",ro,h,minNSampleToA+p),
1468                                           Form("ADC-TOA correlation %d %d %d; TOA (arb. units); ADC (arb. units)",ro,h,minNSampleToA+p),1024/4,0,1024, "");
1469         h2DToAvsADC[ro][h][p]  = new TH2D(Form("h2DADCTOA_Asic_%d_Half_%d_NToASample_%d",ro,h,minNSampleToA+p),
1470                                       Form("2D ADC vs TOA %d %d %d; TOA (arb. units); ADC (arb. units)",ro,h, minNSampleToA+p), 1024/4,0,1024,1124/4,-100,1024);
1471         
1472         hWaveFormHalfAsic[ro][h][p]    = new TProfile(Form("WaveForm_Asic_%d_Half_%d_NToASample_%d",ro,h,minNSampleToA+p),
1473                                           Form("ADC-TOA correlation %d %d %d;  t (ns) ; ADC (arb. units)",ro,h,minNSampleToA+p),550,-50,500);
1474         h2DWaveFormHalfAsic[ro][h][p]  = new TH2D(Form("h2DWaveForm_Asic_%d_Half_%d_NToASample_%d",ro,h,minNSampleToA+p),
1475                                           Form("2D ADC vs TOA %d %d %d;  t (ns) ; ADC (arb. units)",ro,h,minNSampleToA+p), 
1476                                           550,-50,500, 1044/4, -20, 1024);
1477         hToAvsADC[ro][h][p]->SetDirectory(0);
1478         h2DToAvsADC[ro][h][p]->SetDirectory(0);
1479         hWaveFormHalfAsic[ro][h][p]->SetDirectory(0);
1480         h2DWaveFormHalfAsic[ro][h][p]->SetDirectory(0);
1481       }
1482     }
1483   }
1484   
1485   ROOT::Math::MinimizerOptions::SetDefaultMinimizer("Minuit2", "Migrad");  
1486   if (maxEvents == -1){
1487     maxEvents = evts;
1488   } else {
1489     std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
1490     std::cout << "ATTENTION: YOU ARE RESETTING THE MAXIMUM NUMBER OF EVENTS TO BE PROCESSED TO: " << maxEvents << ". THIS SHOULD ONLY BE USED FOR TESTING!" << std::endl;
1491     std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
1492   }
1493   
1494   //==================================================================================
1495   // setup waveform builder for HGCROC data
1496   //==================================================================================
1497   waveform_fit_base *waveform_builder = nullptr;
1498   if (GetHGCROCOptInteg() == 1 || GetHGCROCOptInteg() == 101){
1499     waveform_builder = new max_sample_fit_n_integ(GetHGCROCNSampleInteg());
1500   } else {
1501     waveform_builder = new max_sample_fit();
1502   }
1503   
1504   //==================================================================================
1505   // process events from tree
1506   //==================================================================================
1507   for(int i=0; i<evts && i < maxEvents ; i++){
1508     if (i%5000 == 0&& i > 0 && debug > 0) std::cout << "Reading " <<  i << "/" << evts << " events"<< std::endl;
1509     TdataIn->GetEntry(i); 
1510     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1511     // process tiles in event
1512     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++    
1513     for(int j=0; j<event.GetNTiles(); j++){
1514       //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
1515       // histo filling for HGCROC specific things & resetting of ped
1516       //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++        
1517       Hgcroc* aTile=(Hgcroc*)event.GetTile(j);
1518       int cellID = aTile->GetCellID();
1519       
1520       // get pedestal values from calib object
1521       double ped    = calib.GetPedestalMeanL(cellID);
1522       double pedErr = calib.GetPedestalSigL(cellID);
1523       if (ped == -1000){
1524         ped     = calib.GetPedestalMeanH(cellID);
1525         pedErr  = calib.GetPedestalSigH(cellID);
1526         if (ped == -1000){
1527           ped     = aTile->GetPedestal();
1528           pedErr  = 5;
1529         }
1530       }
1531       // reevaluate waveform
1532       waveform_builder->set_waveform(aTile->GetADCWaveform());
1533       waveform_builder->fit_with_average_ped(ped);
1534       aTile->SetIntegratedADC(waveform_builder->get_E());
1535       aTile->SetPedestal(waveform_builder->get_pedestal());
1536       
1537       // obtain integrated tile quantities for histo filling
1538       double adc      = aTile->GetIntegratedADC();
1539       double toa      = aTile->GetRawTOA();
1540       bool hasTOA     = false;
1541       // check if we have a toa
1542       if (toa > 0)
1543         hasTOA        = true;
1544 
1545       Int_t nSampTOA  = aTile->GetFirstTOASample();        
1546       double toaNs      = (double)aTile->GetLinearizedRawTOA()*aTile->GetTOATimeResolution();
1547       
1548       Int_t nMaxADC   = aTile->GetMaxSampleADC();
1549       Int_t nADCFirst = aTile->GetFirstSampleAboveTh();
1550       Int_t nDiffFirstT= nSampTOA-nADCFirst;
1551       Int_t nDiffFirstM= nMaxADC-nADCFirst;
1552       Int_t nDiffMaxT  = nMaxADC-nSampTOA;
1553       Int_t nOffEmpty  = 2;
1554       
1555       if (hasTOA){
1556         hSampleTOA->Fill(nSampTOA);
1557         hSampleTOAVsCellID->Fill(cellID,nSampTOA);
1558       }
1559       if (adc > ped+2*pedErr){
1560         hSampleMaxADC->Fill(nMaxADC);
1561         hSampleMaxADCVsCellID->Fill(cellID,nMaxADC);
1562         hSampleAboveTh->Fill(nADCFirst);
1563       }
1564       
1565       if (hasTOA && adc > ped+2*pedErr){
1566         hSampleDiff->Fill(nSampTOA-nMaxADC);
1567         hSampleDiffMin->Fill(nSampTOA-nADCFirst);
1568       }
1569       
1570       Int_t asic      = setup->GetROunit(cellID);
1571       Int_t roCh      = setup->GetROchannel(cellID);
1572 
1573       if (hasTOA){
1574         hTOANsVsCellID->Fill(cellID,toaNs);
1575         
1576         // fill overview hists for half asics
1577         h2DToAvsnSample[asic][int(roCh/36)]->Fill(toa, nSampTOA);
1578         for (int k = 0; k < (int)(aTile->GetADCWaveform()).size(); k++ ){
1579           double timetemp = ((k+nOffEmpty)*1024 + (double)aTile->GetLinearizedRawTOA())*aTile->GetTOATimeResolution() ;
1580           hWaveFormHalfAsicAll[asic][int(roCh/36)]->Fill(timetemp,(aTile->GetADCWaveform()).at(k)-ped);
1581           h2DWaveFormHalfAsicAll[asic][int(roCh/36)]->Fill(timetemp,(aTile->GetADCWaveform()).at(k)-ped);
1582         }          
1583         
1584         int binSample = nSampTOA-minNSampleToA;
1585         if (!(nSampTOA > minNSampleToA-1 && nSampTOA < minNSampleToA+5)) continue;
1586         hToAvsADC[asic][int(roCh/36)][binSample]->Fill(toa, adc);
1587         h2DToAvsADC[asic][int(roCh/36)][binSample]->Fill(toa, adc);
1588         for (int k = 0; k < (int)(aTile->GetADCWaveform()).size(); k++ ){
1589           double timetemp = ((k+nOffEmpty)*1024 + (double)aTile->GetLinearizedRawTOA())*aTile->GetTOATimeResolution() ;
1590           hWaveFormHalfAsic[asic][int(roCh/36)][binSample]->Fill(timetemp,(aTile->GetADCWaveform()).at(k)-ped);
1591           h2DWaveFormHalfAsic[asic][int(roCh/36)][binSample]->Fill(timetemp,(aTile->GetADCWaveform()).at(k)-ped);
1592         }          
1593       }        
1594     }
1595   }
1596   RootInput->Close();
1597   //==================================================================================
1598   // Setup general plotting infos
1599   //==================================================================================    
1600   TString outputDirPlots = GetPlotOutputDir();
1601   Double_t textSizeRel = 0.035;
1602 
1603   gSystem->Exec("mkdir -p "+outputDirPlots);
1604   StyleSettingsBasics("pdf");
1605   SetPlotStyle();  
1606   
1607   //==================================================================================
1608   // Create Summary plots
1609   //==================================================================================    
1610   TCanvas* canvas2DSigQA = new TCanvas("canvas2DSigQA","",0,0,1450,1300);  // gives the page size
1611   DefaultCanvasSettings( canvas2DSigQA, 0.08, 0.13, 0.045, 0.07);
1612 
1613   PlotSimple2D( canvas2DSigQA, hSampleTOAVsCellID, (double)it->second.samples,setup->GetMaxCellID()+1, textSizeRel, Form("%s/SampleTOAvsCellID.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
1614   PlotSimple2D( canvas2DSigQA, hSampleMaxADCVsCellID, (double)it->second.samples, setup->GetMaxCellID()+1, textSizeRel, Form("%s/SampleMaxADCvsCellID.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
1615 
1616   PlotSimple2D( canvas2DSigQA, hTOANsVsCellID, -10000, setup->GetMaxCellID()+1, textSizeRel, Form("%s/TOANsvsCellID.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
1617   
1618   canvas2DSigQA->SetLogz(1);
1619   
1620   Int_t diffBins = 4;
1621     
1622   for (int p = 0; p< 5; p++){
1623     std::cout << "************************************************" << std::endl;
1624     std::cout << "TOA offset estimate: " << std::endl; 
1625     std::cout << "nSample ToA: " << p+minNSampleToA << std::endl; 
1626     std::cout << "nCells in sample: " << hSampleTOA->GetBinContent(hSampleTOA->FindBin(p+minNSampleToA+0.001)) << std::endl;
1627     std::cout << "************************************************" << std::endl;
1628     std::cout << "# ASIC\tHalf\tOffset" << std::endl;
1629     TString outputDirNameToa=Form("%s/nToA_%d",outputDirPlots.Data(), p+minNSampleToA);
1630     gSystem->Exec("mkdir -p "+outputDirNameToa);
1631     for (Int_t ro = 0; ro < setup->GetNMaxROUnit()+1; ro++){
1632       for (int h = 0; h< 2; h++){ 
1633         
1634         Double_t largestDiff = 0.;
1635         Int_t bin         = 1;
1636         for (Int_t b = 1; b < hToAvsADC[ro][h][p]->GetNbinsX(); b++){
1637           Int_t maxBin  = (b+diffBins);
1638           if (maxBin > hToAvsADC[ro][h][p]->GetNbinsX()){
1639             maxBin      = maxBin-hToAvsADC[ro][h][p]->GetNbinsX();
1640           }
1641           Double_t diff = hToAvsADC[ro][h][p]->GetBinContent(maxBin) - hToAvsADC[ro][h][p]->GetBinContent(b);
1642           if (largestDiff < diff){
1643             largestDiff = diff;
1644             bin         = b;
1645           }
1646         }
1647         Int_t centerbin = bin+Int_t(diffBins/2);
1648         if (centerbin > (hToAvsADC[ro][h][p]->GetNbinsX()-diffBins/2))
1649           centerbin     = centerbin-(hToAvsADC[ro][h][p]->GetNbinsX()-diffBins/2);
1650         
1651         Int_t offset = (Int_t)(hToAvsADC[ro][h][p]->GetBinCenter(centerbin));
1652         std::cout << ro <<"\t" <<h << "\t" << offset << std::endl;
1653         
1654         Plot2DWithProfile( canvas2DSigQA, h2DToAvsADC[ro][h][p], hToAvsADC[ro][h][p], -10000, -10000, textSizeRel,
1655                           Form("%s/ToAvsADC_Asic_%d_Half_%d_NToASample_%d.%s", outputDirNameToa.Data(), ro, h,p+minNSampleToA, plotSuffix.Data()), 
1656                           it->second, 1, kFALSE, "colz",true, Form("Asic %d, Half %d,  nSample ToA: %d",ro,h, p+minNSampleToA), offset);
1657         
1658         h2DWaveFormHalfAsic[ro][h][p]->GetXaxis()->SetRangeUser(-25, (it->second.samples)*25);
1659         Plot2DWithProfile( canvas2DSigQA, h2DWaveFormHalfAsic[ro][h][p], hWaveFormHalfAsic[ro][h][p], -10000, -10000, textSizeRel,
1660                           Form("%s/Waveform_Asic_%d_Half_%d_NToASample_%d.%s", outputDirNameToa.Data(), ro, h, p+minNSampleToA, plotSuffix.Data()), 
1661                           it->second, 1, kFALSE, "colz",true, Form("Asic %d, Half %d, nSample ToA: %d",ro,h, p+minNSampleToA), -1);
1662       }
1663     }
1664   }
1665   
1666   for (Int_t ro = 0; ro < setup->GetNMaxROUnit()+1; ro++){
1667     for (int h = 0; h< 2; h++){      
1668         PlotSimple2D( canvas2DSigQA, h2DToAvsnSample[ro][h],(double)it->second.samples, -10000, textSizeRel,
1669                           Form("%s/ToaVsNSample_Asic_%d_Half_%d.%s", outputDirPlots.Data(), ro, h, plotSuffix.Data()), 
1670                           it->second, 1, kFALSE, "colz",true, Form("Asic %d, Half %d",ro,h));
1671         h2DWaveFormHalfAsicAll[ro][h]->GetXaxis()->SetRangeUser(-25, (it->second.samples)*25);
1672         Plot2DWithProfile( canvas2DSigQA, h2DWaveFormHalfAsicAll[ro][h], hWaveFormHalfAsicAll[ro][h], -10000, -10000, textSizeRel,
1673                           Form("%s/Waveform_Asic_%d_Half_%d.%s", outputDirPlots.Data(), ro, h, plotSuffix.Data()), 
1674                           it->second, 1, kFALSE, "colz",true, Form("Asic %d, Half %d",ro,h), -1);
1675     }
1676   }
1677 
1678   TCanvas* canvas1DSimple = new TCanvas("canvas1DSimple","",0,0,1450,1300);  // gives the page size
1679   DefaultCanvasSettings( canvas1DSimple, 0.08, 0.03, 0.03, 0.07);
1680 
1681   PlotSimple1D(canvas1DSimple, hSampleTOA, -10000, (double)it->second.samples, textSizeRel, Form("%s/NSampleToA.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1);
1682   PlotSimple1D(canvas1DSimple, hSampleMaxADC, -10000, (double)it->second.samples, textSizeRel, Form("%s/NSampleMaxADC.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1);
1683   PlotSimple1D(canvas1DSimple, hSampleAboveTh, -10000, (double)it->second.samples, textSizeRel, Form("%s/NSampleAboveTh.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1);
1684   PlotSimple1D(canvas1DSimple, hSampleDiff, -10000, (double)it->second.samples, textSizeRel, Form("%s/NSampleDiff.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1);
1685   PlotSimple1D(canvas1DSimple, hSampleDiffMin, -10000, (double)it->second.samples, textSizeRel, Form("%s/NSampleDiffMin.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1);
1686   
1687   //=====================================================================
1688   // Write output histograms
1689   //=====================================================================
1690   RootOutputHist->cd();
1691     hSampleTOA->Write();
1692     hSampleMaxADC->Write();
1693     hSampleAboveTh->Write();
1694     hSampleDiff->Write();
1695     hSampleDiffMin->Write();
1696     hSampleTOAVsCellID->Write();
1697     hTOANsVsCellID->Write();
1698     hSampleMaxADCVsCellID->Write();
1699 
1700     for (Int_t ro = 0; ro < setup->GetNMaxROUnit()+1; ro++){
1701       for (int h = 0; h< 2; h++){
1702         h2DToAvsnSample[ro][h]->Write();
1703         h2DWaveFormHalfAsicAll[ro][h]->Write();
1704         hWaveFormHalfAsicAll[ro][h]->Write();
1705         for (int p = 0; p< 5; p++){
1706           hToAvsADC[ro][h][p]->Write();
1707           h2DToAvsADC[ro][h][p]->Write();
1708           h2DWaveFormHalfAsic[ro][h][p]->Write();
1709           hWaveFormHalfAsic[ro][h][p]->Write();
1710         }
1711       }
1712     }
1713   RootOutputHist->Close();
1714   
1715   return true;
1716 } // end Analyses::EvaluateHGCROCToAPhases()
1717 
1718 
1719 // ****************************************************************************
1720 // extract pedestral from dedicated data run, no other data in run 
1721 // ****************************************************************************
1722 bool Analyses::TransferCalib(void){
1723   std::cout<<"Transfer calib"<<std::endl;
1724   int evts=TdataIn->GetEntries();
1725 
1726   // initialize lookup-table run list
1727   std::map<int,RunInfo> ri=readRunInfosFromFile(RunListInputName.Data(),debug,0);
1728   std::map<int,TileSpectra> hSpectra;
1729   std::map<int, TileSpectra>::iterator ithSpectra;
1730   std::map<int,TileSpectra> hSpectraTrigg;
1731   std::map<int, TileSpectra>::iterator ithSpectraTrigg;
1732 
1733   
1734   // initialize calib
1735   TcalibIn->GetEntry(0);
1736   // check whether calib should be overwritten based on external text file
1737   if (OverWriteCalib){
1738     calib.ReadCalibFromTextFile(ExternalCalibFile,debug);
1739   }
1740   // add ToA offsets for half asics to calib objects if available
1741   if (ExternalToACalibOffSetFile.CompareTo("") != 0 ){
1742     calib.ReadExternalToAOffsets(ExternalToACalibOffSetFile,debug);
1743   }
1744   std::map<int,short> bcmap;
1745   std::map<int,short>::iterator bcmapIte;
1746   if (CalcBadChannel == 1)
1747     bcmap = ReadExternalBadChannelMap();
1748   
1749   // intialize run infos & reset calib object to correct run number
1750   TdataIn->GetEntry(0);     // use first event to get infos
1751   int runNr             = event.GetRunNumber();
1752   std::map<int,RunInfo>::iterator it=ri.find(runNr);
1753   ReadOut::Type typeRO  = event.GetROtype();
1754   double VopE            = event.GetVop();
1755   double VopRL           = it->second.vop;
1756   std::cout<< "original run numbers calib: "<<calib.GetRunNumber() << "\t" << calib.GetRunNumberPed() << "\t" << calib.GetRunNumberMip() << std::endl;
1757   calib.SetRunNumber(runNr);
1758   calib.SetBeginRunTime(event.GetBeginRunTimeAlt());
1759   if (VopE != calib.GetVop() || VopRL != calib.GetVop()){
1760     std::cout << "Calibration applied and current run have different Vop: \n \t - calib: "  << calib.GetVop() << "\n \t- current: " << VopRL << "\n \t\t RESETTING to current run Vop & Vov!!" << std::endl;
1761     calib.SetVop(VopRL);
1762     calib.SetVov(VopRL-it->second.vbr);
1763   }
1764   std::cout<< "reset run numbers calib: "<< calib.GetRunNumber() << "\t" << calib.GetRunNumberPed() << "\t" << calib.GetRunNumberMip() << std::endl;
1765   
1766 
1767   
1768   // Find detector config
1769   DetConf::Type detConf = setup->GetDetectorConfig();
1770   if (it->second.detector == "FoCal-H" || (it->second.detector).Contains("FoCal"))
1771     detConf = DetConf::Type::FocalH; 
1772 
1773   //==================================================================================
1774   // create additional output hist 
1775   //==================================================================================
1776   if (!CreateOutputRootHistFile()) return false;
1777 
1778   int maxChanneTransferCaliblPerLayer       = (setup->GetNMaxColumn()+1)*(setup->GetNMaxRow()+1)*(setup->GetNMaxModule()+1);
1779   int maxChannelPerLayerSingleMod           = (setup->GetNMaxColumn()+1)*(setup->GetNMaxRow()+1);
1780 
1781   // HGCROC specific histo creation
1782   TH2D* hspectraADCvsCellID         = nullptr;
1783   TH2D* hspectraADCPedvsCellID      = nullptr;
1784   TH2D* hHighestADCAbovePedVsLayer  = nullptr;
1785   TH2D* hspectraTOTvsCellID   =nullptr;
1786   TH2D* hspectraTOAvsCellID   =nullptr;   
1787   TH2D* hSampleTOAVsCellID    =nullptr;
1788   TH1D* hSampleTOA            =nullptr;   
1789   TH2D* hTOANsVsCellID        =nullptr;   
1790   TH2D* hTOACorrNsVsCellID    =nullptr;   
1791   TH2D* hNCellsWTOAVsTotADC   =nullptr;
1792   TH2D* hNCellsWmADCVsTotADC  =nullptr;        
1793   // plot setup per half asic for ToA 
1794   std::vector<std::array<TH2D*, 2>> h2DToAvsnSample(setup->GetNMaxROUnit()+1);
1795   std::vector<std::array<TH2D*, 2>> h2DWaveFormHalfAsicAll(setup->GetNMaxROUnit()+1);
1796   std::vector<std::array<TProfile*, 2>> hWaveFormHalfAsicAll(setup->GetNMaxROUnit()+1);
1797   
1798   // only create these if we have an HGCROC data type as input
1799   if (typeRO == ReadOut::Type::Hgcroc){
1800     hspectraADCvsCellID      = new TH2D( "hspectraADCvsCellID","ADC spectrums CellID; cell ID; ADC (arb. units) ",
1801                                               setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5, 1024,0,1024);
1802     hspectraADCvsCellID->SetDirectory(0);
1803     
1804     hspectraADCPedvsCellID      = new TH2D( "hspectraADCPedvsCellID","Pedestal ADC spectrums CellID; cell ID; ADC (arb. units) ",
1805                                               setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5, 1024,0,1024);
1806     hspectraADCPedvsCellID->SetDirectory(0);
1807     
1808     hHighestADCAbovePedVsLayer   = new TH2D( "hHighestEAbovePedVsLayer","Highest ADC above PED; layer; brd channel; #Sigma(ADC) (arb. units) ",
1809                                               setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChanneTransferCaliblPerLayer, -0.5, maxChanneTransferCaliblPerLayer-0.5);
1810     hHighestADCAbovePedVsLayer->SetDirectory(0);
1811     hHighestADCAbovePedVsLayer->Sumw2();
1812     hspectraTOTvsCellID      = new TH2D( "hspectraTOTvsCellID","TOT spectrums CellID; cell ID; TOT (arb. units) ",
1813                                             setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5, 4096,0,4096);
1814     hspectraTOTvsCellID->SetDirectory(0);
1815     hspectraTOAvsCellID      = new TH2D( "hspectraTOAvsCellID","TOA spectrums CellID; cell ID; TOA (arb. units) ",
1816                                             setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5, 1024,0,1024);
1817     hspectraTOAvsCellID->SetDirectory(0);
1818     hSampleTOAVsCellID       = new TH2D( "hSampleTOAvsCellID","#sample ToA; cell ID; #sample TOA",
1819                                             setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5, it->second.samples,0,it->second.samples);
1820     hSampleTOAVsCellID->SetDirectory(0);
1821     hSampleTOA                = new TH1D( "hSampleTOA","#sample ToA; #sample TOA",
1822                                               it->second.samples,0,it->second.samples);
1823     hSampleTOA->SetDirectory(0);
1824     hTOANsVsCellID            = new TH2D( "hTOANsVsCellID","ToA (ns); cell ID; ToA (ns)",
1825                                       setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5, 500,-250,0);
1826     hTOANsVsCellID->SetDirectory(0);
1827     hTOACorrNsVsCellID        = new TH2D( "hTOACorrNsVsCellID","ToA (ns); cell ID; ToA (ns)",
1828                                       setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5, 500,-250,0);
1829     hTOACorrNsVsCellID->SetDirectory(0);
1830     
1831     hNCellsWTOAVsTotADC          = new TH2D( "hNCellsWTOAVsTotADC","NCells above TOA vs tot ADC; NCells above TOA; #Sigma(ADC) (arb. units) ",
1832                                             setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5, 5000,0,10000);
1833     hNCellsWTOAVsTotADC->SetDirectory(0);
1834     hNCellsWmADCVsTotADC          = new TH2D( "hNCellsWmADCVsTotADC","NCells w. ADC > 10 vs tot ADC; NCells above min ADC; #Sigma(ADC) (arb. units) ",
1835                                             setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5, 5000,0,10000);
1836     hNCellsWmADCVsTotADC->SetDirectory(0);
1837 
1838     for (Int_t ro = 0; ro < setup->GetNMaxROUnit()+1; ro++){
1839       for (int h = 0; h< 2; h++){
1840         h2DToAvsnSample[ro][h]    = new TH2D(Form("h2DTOASample_Asic_%d_Half_%d",ro,h),
1841                                               Form("Sample vs TOA %d %d; TOA (arb. units); #sample",ro,h), 1024/8,0,1024,it->second.samples,0,it->second.samples);
1842         h2DToAvsnSample[ro][h]->SetDirectory(0);
1843         hWaveFormHalfAsicAll[ro][h]    = new TProfile(Form("WaveForm_Asic_%d_Half_%d",ro,h),
1844                                           Form("ADC-TOA correlation %d %d;  t (ns) ; ADC (arb. units)",ro,h),550,-50,500);
1845         hWaveFormHalfAsicAll[ro][h]->SetDirectory(0);
1846         h2DWaveFormHalfAsicAll[ro][h]  = new TH2D(Form("h2DWaveForm_Asic_%d_Half_%d",ro,h),
1847                                           Form("2D ADC vs TOA %d %d;  t (ns) ; ADC (arb. units)",ro,h), 
1848                                             550,-50,500, 1044/4, -20, 1024);      
1849         h2DWaveFormHalfAsicAll[ro][h]->SetDirectory(0);
1850       }
1851     }
1852   } 
1853   
1854   RootOutputHist->mkdir("IndividualCells");
1855   if(typeRO == ReadOut::Type::Hgcroc) RootOutputHist->mkdir("IndividualCellsTrigg");
1856   if(typeRO == ReadOut::Type::Caen) RootOutputHist->mkdir("IndividualCellsRejected");
1857   RootOutputHist->cd("IndividualCells");
1858   
1859   ROOT::Math::MinimizerOptions::SetDefaultMinimizer("Minuit2", "Migrad");  
1860   if (maxEvents == -1){
1861     maxEvents = evts;
1862   } else {
1863     std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
1864     std::cout << "ATTENTION: YOU ARE RESETTING THE MAXIMUM NUMBER OF EVENTS TO BE PROCESSED TO: " << maxEvents << ". THIS SHOULD ONLY BE USED FOR TESTING!" << std::endl;
1865     std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
1866   }
1867   
1868   if (EventCleanup == 1){
1869     std::cout << "==============================================================================" << std::endl;
1870     std::cout << "==============================================================================" << std::endl;
1871     if (calib.GetAverageScaleHigh() != -10000 ){
1872       std::cout << "resetting rejection thresholds with average HG Scale" << std::endl;
1873       cleanupLGTh   =  ((calib.GetAverageScaleHigh()-calib.GetAverageLGHGCorrOff())/calib.GetAverageLGHGCorr() )* 2.5;
1874       cleanupHGTh   =  calib.GetAverageScaleHigh()*1.5;
1875     }
1876     std::cout << "Thresholds for rejections: \t LG: " << cleanupLGTh << "\t HG: " << cleanupHGTh << std::endl;
1877     std::cout << "==============================================================================" << std::endl;
1878     std::cout << "==============================================================================" << std::endl;
1879   }
1880   
1881   //==================================================================================
1882   // setup waveform builder for HGCROC data
1883   //==================================================================================
1884   waveform_fit_base *waveform_builder = nullptr;
1885   if (GetHGCROCOptInteg() == 1 || GetHGCROCOptInteg() == 101){
1886     waveform_builder = new max_sample_fit_n_integ(GetHGCROCNSampleInteg());
1887   } else {
1888     waveform_builder = new max_sample_fit();
1889   }
1890   double minNSigma = 5;
1891   int nCellsAboveTOA  = 0;
1892   int nCellsAboveMADC = 0;
1893   double totADCs      = 0.;
1894   int rejectedEvents  = 0;
1895   //==================================================================================
1896   // process events from tree:
1897   // - fill spectra plots for cross checking
1898   // - HGCROC data: 
1899   //     * set pedestal values from externally processed data
1900   //     * reevaluate waveform fits
1901   //     * plot waveforms
1902   //==================================================================================
1903   for(int i=0; i<evts && i < maxEvents ; i++){
1904     if (i%5000 == 0&& i > 0 && debug > 0) std::cout << "Reading " <<  i << "/" << evts << " events"<< std::endl;
1905     if (debug > 2 && typeRO == ReadOut::Type::Hgcroc){
1906       std::cout << "************************************* NEW EVENT " << i << "  *********************************" << std::endl;
1907     }
1908     TdataIn->GetEntry(i);
1909    
1910     bool bREvent = false;
1911     if (EventCleanup == 1){
1912       if (!event.CheckEventIntegrity(calib, cleanupLGTh, cleanupHGTh)){
1913         rejectedEvents++;
1914         bREvent = true;
1915         // continue;
1916       }
1917     }
1918     
1919     // initialize counters per event
1920     nCellsAboveTOA  = 0;
1921     nCellsAboveMADC = 0;
1922     totADCs         = 0.;
1923     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1924     // process tiles in event
1925     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1926     for(int j=0; j<event.GetNTiles(); j++){
1927       //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1928       // histo filling for CAEN specific things
1929       //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1930       if (typeRO == ReadOut::Type::Caen) {
1931         Caen* aTile=(Caen*)event.GetTile(j);
1932         ithSpectra      = hSpectra.find(aTile->GetCellID());
1933         ithSpectraTrigg = hSpectraTrigg.find(aTile->GetCellID());
1934         double hgCorr = aTile->GetADCHigh()-calib.GetPedestalMeanH(aTile->GetCellID());
1935         double lgCorr = aTile->GetADCLow()-calib.GetPedestalMeanL(aTile->GetCellID());
1936         // fill spectra histos
1937         if (!bREvent){
1938           if(ithSpectra!=hSpectra.end()){
1939             ithSpectra->second.FillExtCAEN(lgCorr,hgCorr, 0., 0.);
1940           } else {
1941             RootOutputHist->cd("IndividualCells");
1942             hSpectra[aTile->GetCellID()]=TileSpectra("All",2,aTile->GetCellID(),calib.GetTileCalib(aTile->GetCellID()),event.GetROtype(), nSampleHGCROCInt, debug);
1943             hSpectra[aTile->GetCellID()].FillExtCAEN(lgCorr,hgCorr, 0., 0.);
1944             RootOutput->cd();
1945           }
1946         } else {
1947           if(ithSpectraTrigg!=hSpectraTrigg.end()){
1948             ithSpectraTrigg->second.FillExtCAEN(lgCorr,hgCorr, 0., 0.);
1949           } else {
1950             RootOutputHist->cd("IndividualCellsRejected");
1951             hSpectraTrigg[aTile->GetCellID()]=TileSpectra("Rejected",2,aTile->GetCellID(),calib.GetTileCalib(aTile->GetCellID()),event.GetROtype(), nSampleHGCROCInt, debug);
1952             hSpectraTrigg[aTile->GetCellID()].FillExtCAEN(lgCorr,hgCorr, 0., 0.);
1953             RootOutput->cd();
1954           }
1955         }
1956       //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
1957       // histo filling for HGCROC specific things & resetting of ped
1958       //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1959       } else if (typeRO == ReadOut::Type::Hgcroc) {
1960         Hgcroc* aTile=(Hgcroc*)event.GetTile(j);
1961         int cellID    = aTile->GetCellID();
1962         ithSpectra=hSpectra.find(cellID);
1963         ithSpectraTrigg=hSpectraTrigg.find(cellID);
1964         
1965         // get pedestal values from calib object
1966         double ped = calib.GetPedestalMeanL(cellID); // ped based on waveform fit
1967         if (ped == -1000){
1968           ped = calib.GetPedestalMeanH(cellID);      // ped based on first sample fit
1969           if (ped == -1000){
1970             ped = aTile->GetPedestal();              // event-by-event first sample
1971           }
1972         }
1973         // reevaluate waveform
1974         waveform_builder->set_waveform(aTile->GetADCWaveform());
1975         waveform_builder->fit_with_average_ped(ped);
1976         aTile->SetIntegratedADC(waveform_builder->get_E());
1977         aTile->SetPedestal(waveform_builder->get_pedestal());
1978         
1979         // obtain integrated tile quantities for histo filling
1980         int layer     = setup->GetLayer(cellID);
1981         int chInLayer = setup->GetChannelInLayerFull(cellID, detConf);
1982         double adc = aTile->GetIntegratedADC();
1983         double tot = aTile->GetRawTOT();
1984         double toa = aTile->GetRawTOA();
1985         bool hasTOA     = false;
1986         bool hasTOT     = false;
1987         
1988         // check if we have a toa
1989         if (toa > 0)
1990           hasTOA        = true;
1991         // check if we have a tot
1992         if (tot > 0)
1993           hasTOT        = true;
1994         // obtain toa shift corrected values
1995         Int_t nSampTOA  = aTile->GetFirstTOASample();        
1996         double toaNs      = (double)aTile->GetLinearizedRawTOA()*aTile->GetTOATimeResolution();
1997         double toaCorrNs  = toaNs;
1998         Int_t nOffEmpty   = 2;
1999         if (calib.GetToAOff(cellID) != -1000.){
2000           // correct ToA sample and return correct nSampleTOA
2001           nSampTOA      = aTile->SetCorrectedTOA(calib.GetToAOff(cellID)); 
2002           toaCorrNs     = (double)(aTile->GetCorrectedTOA())*aTile->GetTOATimeResolution();;
2003         }
2004         totADCs         = totADCs+adc;
2005         if (adc > 10)
2006           nCellsAboveMADC++; 
2007         if (toa > 0)
2008           nCellsAboveTOA++;
2009         
2010         hspectraADCvsCellID->Fill(cellID,adc);
2011         hspectraADCPedvsCellID->Fill(cellID,aTile->GetPedestal());
2012         if(hasTOT)  hspectraTOTvsCellID->Fill(cellID,tot);
2013         
2014         Int_t asic      = setup->GetROunit(cellID);
2015         Int_t roCh      = setup->GetROchannel(cellID);
2016         if (hasTOA){
2017           hspectraTOAvsCellID->Fill(cellID,toa);
2018           hSampleTOAVsCellID->Fill(cellID,nSampTOA);
2019           hSampleTOA->Fill(nSampTOA);
2020           hTOANsVsCellID->Fill(cellID,toaNs);
2021           hTOACorrNsVsCellID->Fill(cellID,toaCorrNs);
2022           // fill overview hists for half asics
2023           h2DToAvsnSample[asic][int(roCh/36)]->Fill(toa, nSampTOA);
2024           for (int k = 0; k < (int)(aTile->GetADCWaveform()).size(); k++ ){
2025             double timetemp = ((k+nOffEmpty)*1024 + (double)aTile->GetCorrectedTOA())*aTile->GetTOATimeResolution() ;
2026             hWaveFormHalfAsicAll[asic][int(roCh/36)]->Fill(timetemp,(aTile->GetADCWaveform()).at(k)-ped);
2027             h2DWaveFormHalfAsicAll[asic][int(roCh/36)]->Fill(timetemp,(aTile->GetADCWaveform()).at(k)-ped);
2028           }          
2029         }        
2030         
2031         // single tile debug info print
2032         if (debug > 10 ){
2033           aTile->PrintWaveFormDebugInfo(calib.GetPedestalMeanH(cellID), calib.GetPedestalMeanL(cellID), calib.GetPedestalSigL(cellID));
2034         }
2035         // fill spectra histos
2036         if(ithSpectra!=hSpectra.end()){
2037           ithSpectra->second.FillExtHGCROC(adc,toa,tot,nSampTOA,-1);
2038           ithSpectra->second.FillWaveform(aTile->GetADCWaveform(),0);
2039         } else {
2040           RootOutputHist->cd("IndividualCells");
2041           hSpectra[cellID]=TileSpectra("All",2,cellID,calib.GetTileCalib(cellID),event.GetROtype(), nSampleHGCROCInt, debug);
2042           hSpectra[cellID].FillExtHGCROC(adc,toa,tot,nSampTOA,-1);
2043           hSpectra[cellID].FillWaveform(aTile->GetADCWaveform(),0);
2044           RootOutput->cd();
2045         }
2046         // Select only signals with a TOA (cleanup )      
2047         if (hasTOA){      
2048             hHighestADCAbovePedVsLayer->Fill(layer,chInLayer, adc);
2049           
2050           if(ithSpectraTrigg!=hSpectraTrigg.end()){
2051             ithSpectraTrigg->second.FillExtHGCROC(adc,toa,tot,nSampTOA,-1);
2052             ithSpectraTrigg->second.FillWaveform(aTile->GetADCWaveform(),0);
2053           } else {
2054             RootOutputHist->cd("IndividualCellsTrigg");
2055             hSpectraTrigg[cellID]=TileSpectra("signal",2,cellID,calib.GetTileCalib(cellID),event.GetROtype(), nSampleHGCROCInt, debug);
2056             hSpectraTrigg[cellID].FillExtHGCROC(adc,toa,tot,nSampTOA,-1);
2057             hSpectraTrigg[cellID].FillWaveform(aTile->GetADCWaveform(),0);
2058             RootOutput->cd();
2059           }
2060         }
2061       }
2062     }
2063     // summary plot filling HGCROC
2064     if (typeRO == ReadOut::Type::Hgcroc) {
2065       hNCellsWmADCVsTotADC->Fill(nCellsAboveMADC, totADCs);
2066       hNCellsWTOAVsTotADC->Fill(nCellsAboveTOA, totADCs);
2067     }
2068     RootOutput->cd();
2069     // fill tree
2070     if (!bREvent) TdataOut->Fill();
2071   }
2072   // write tree
2073   TdataOut->Write();
2074   TsetupIn->CloneTree()->Write();
2075 
2076   if (EventCleanup == 1){
2077     std::cout << "****************************************************************************************************"<< std::endl; 
2078     std::cout << "****************************************************************************************************"<< std::endl; 
2079     std::cout << rejectedEvents<< "\t/" << maxEvents  << " rejected CAEN events due to corrupted data for single channels!"<< std::endl; 
2080     std::cout << "****************************************************************************************************"<< std::endl; 
2081     std::cout << "****************************************************************************************************"<< std::endl; 
2082   }
2083   //==================================================================================
2084   // Setup general plotting infos
2085   //==================================================================================  
2086   TString outputDirPlots = GetPlotOutputDir();
2087   Double_t textSizeRel = 0.035;
2088 
2089   if (CalcBadChannel > 0 || ExtPlot > 0) {
2090     gSystem->Exec("mkdir -p "+outputDirPlots);
2091     StyleSettingsBasics("pdf");
2092     SetPlotStyle();  
2093   }
2094   
2095   //==================================================================================
2096   // Internal evaluation for bad channels or application of external bad channel map
2097   //==================================================================================
2098   if (CalcBadChannel > 0 ){
2099     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
2100     // Create monitoring histos for BC extraction
2101     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
2102     int maxChannelPerLayer             = (setup->GetNMaxColumn()+1)*(setup->GetNMaxRow()+1)*(setup->GetNMaxModule()+1);
2103     int maxChannelPerLayerSingleMod    = (setup->GetNMaxColumn()+1)*(setup->GetNMaxRow()+1);
2104 
2105     // monitoring applied pedestals
2106     TH1D* hBCvsCellID      = new TH1D( "hBC_vsCellID","Bad Channel vs CellID ; cell ID; BC flag ",
2107                                               setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5);
2108     hBCvsCellID->SetDirectory(0);
2109     TH2D* hBCVsLayer   = new TH2D( "hBCVsLayer","Bad Channel Map; layer; brd channel; BC flag  ",
2110                                               setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
2111     hBCVsLayer->SetDirectory(0);
2112 
2113     int currCells = 0;
2114     if ( debug > 0 && CalcBadChannel == 2)
2115       std::cout << "============================== starting bad channel extraction" << std::endl;
2116     if ( debug > 0 && CalcBadChannel == 1)
2117       std::cout << "============================== setting bad channel according to external map" << std::endl;
2118     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
2119     // evaluate each tile spectrum & set BC flag
2120     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
2121     for(ithSpectra=hSpectra.begin(); ithSpectra!=hSpectra.end(); ++ithSpectra){
2122       if (currCells%20 == 0 && currCells > 0 && debug > 0)
2123         std::cout << "============================== cell " <<  currCells << " / " << hSpectra.size() << " cells" << std::endl;
2124       currCells++;
2125       short bc   = 3;
2126       // evaluate bad channel map internally
2127       if (CalcBadChannel == 2){
2128         bc        = ithSpectra->second.DetermineBadChannel();
2129       // apply external bad channel map
2130       } else if (CalcBadChannel == 1 && bcmap.size() > 0 ) {
2131         bcmapIte  = bcmap.find(ithSpectra->second.GetCellID());
2132         if(bcmapIte!=bcmap.end())
2133           bc        = bcmapIte->second;
2134         else 
2135           bc        = 3;
2136       } 
2137       
2138       long cellID   = ithSpectra->second.GetCellID();
2139       if (CalcBadChannel == 1)
2140         ithSpectra->second.SetBadChannelInCalib(bc);
2141       
2142       // initializing pedestal fits from calib file
2143       ithSpectra->second.InitializeNoiseFitsFromCalib();
2144       
2145       // histo filling
2146       int layer     = setup->GetLayer(cellID);
2147       int chInLayer = setup->GetChannelInLayerFull(cellID,detConf);
2148       if (debug > 0 && bc > -1 && bc < 3)
2149         std::cout << "\t" << cellID << "\t" << layer << "\t" << setup->GetRow(cellID) << "\t" << setup->GetColumn(cellID)<< "\t" << setup->GetModule(cellID) << " - quality flag: " << bc << "\t" << calib.GetBadChannel(cellID) << "\t ped H: " << calib.GetPedestalMeanH(cellID) << "\t ped L: " << calib.GetPedestalMeanL(cellID)<< std::endl;
2150 
2151       hBCvsCellID->SetBinContent(hBCvsCellID->FindBin(cellID), calib.GetBadChannel(cellID));
2152       int bin2D     = hBCVsLayer->FindBin(layer,chInLayer);
2153       hBCVsLayer->SetBinContent(bin2D, calib.GetBadChannel(cellID));
2154       
2155       if (bc < 2 && typeRO == ReadOut::Type::Hgcroc){
2156         hHighestADCAbovePedVsLayer->SetBinContent(bin2D, 0);
2157       }
2158     }
2159     hBCvsCellID->Write();
2160     hBCVsLayer->Write();
2161 
2162     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
2163     // Create canvases for channel overview plotting
2164     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
2165     // Get run info object
2166     // create directory for plot output
2167   
2168     TCanvas* canvas2DCorr = new TCanvas("canvasCorrPlots","",0,0,1450,1300);  // gives the page size
2169     DefaultCanvasSettings( canvas2DCorr, 0.08, 0.13, 0.045, 0.07);
2170 
2171     canvas2DCorr->SetLogz(0);
2172     
2173     PlotSimple2DZRange( canvas2DCorr, hBCVsLayer, -10000, -10000, -0.1, 3.1, textSizeRel, Form("%s/BadChannelMap.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, "colz", true);    
2174     calib.SetBCCalib(true);
2175   }
2176   
2177   //==================================================================================
2178   // write calib output to root-tree output file
2179   //==================================================================================  
2180   RootOutput->cd();
2181   // print calib file to text file
2182   std::cout<<"What is the value? <ped mean high>: "<<calib.GetAveragePedestalMeanHigh() << "\t good channels: " << calib.GetNumberOfChannelsWithBCflag(3) <<std::endl;
2183   if (IsCalibSaveToFile()){
2184     TString fileCalibPrint = RootOutputName;
2185     fileCalibPrint         = fileCalibPrint.ReplaceAll(".root","_calib.txt");
2186     calib.PrintCalibToFile(fileCalibPrint);
2187   }
2188   // write calib output to 
2189   TcalibOut->Fill();
2190   TcalibOut->Write();
2191   // close file
2192   RootOutput->Close();
2193 
2194   //==================================================================================
2195   // write histo output to file as cross check
2196   //==================================================================================    
2197   RootOutputHist->cd();
2198   if (typeRO == ReadOut::Type::Hgcroc){
2199     hSampleTOA->Write();
2200     hSampleTOAVsCellID->Write();
2201     hTOANsVsCellID->Write();
2202     hTOACorrNsVsCellID->Write();
2203     hspectraADCvsCellID->Write();
2204     hspectraADCPedvsCellID->Write();
2205     hspectraTOTvsCellID->Write();
2206     hspectraTOAvsCellID->Write();
2207     hHighestADCAbovePedVsLayer->Write();
2208     hNCellsWmADCVsTotADC->Write();
2209     hNCellsWTOAVsTotADC->Write();
2210     for (Int_t ro = 0; ro < setup->GetNMaxROUnit()+1; ro++){
2211       for (int h = 0; h< 2; h++){
2212         h2DToAvsnSample[ro][h]->Write();
2213         h2DWaveFormHalfAsicAll[ro][h]->Write();
2214         hWaveFormHalfAsicAll[ro][h]->Write();
2215       }
2216     }
2217   }
2218   // save individual cell spectra
2219   RootOutputHist->cd("IndividualCells");
2220   for(ithSpectra=hSpectra.begin(); ithSpectra!=hSpectra.end(); ++ithSpectra){
2221     ithSpectra->second.WriteExt(true);
2222   }
2223   if (typeRO == ReadOut::Type::Hgcroc){
2224     RootOutputHist->cd("IndividualCellsTrigg");
2225     for(ithSpectraTrigg=hSpectraTrigg.begin(); ithSpectraTrigg!=hSpectraTrigg.end(); ++ithSpectraTrigg){
2226       ithSpectraTrigg->second.WriteExt(true);
2227     }
2228   } else if (EventCleanup) {
2229     RootOutputHist->cd("IndividualCellsRejected");
2230     for(ithSpectraTrigg=hSpectraTrigg.begin(); ithSpectraTrigg!=hSpectraTrigg.end(); ++ithSpectraTrigg){
2231       ithSpectraTrigg->second.WriteExt(true);
2232     }
2233   }
2234   // close root histo output file
2235   RootOutputHist->Close();
2236   // close root input file
2237   RootInput->Close();
2238   
2239   //==================================================================================
2240   // Create plots in case extended plotting is enabled for waveforms
2241   //==================================================================================
2242   if (ExtPlot > 0){
2243     if (typeRO == ReadOut::Type::Hgcroc){
2244       TCanvas* canvas2DSigQA = new TCanvas("canvas2DSigQA","",0,0,1450,1300);  // gives the page size
2245       DefaultCanvasSettings( canvas2DSigQA, 0.08, 0.13, 0.045, 0.07);
2246       
2247       PlotSimple2D( canvas2DSigQA, hTOANsVsCellID, -10000, setup->GetMaxCellID()+1, textSizeRel, Form("%s/TOANsvsCellID.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
2248       PlotSimple2D( canvas2DSigQA, hTOACorrNsVsCellID, -10000, setup->GetMaxCellID()+1, textSizeRel, Form("%s/TOACorrNsvsCellID.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
2249       PlotSimple2D( canvas2DSigQA, hSampleTOAVsCellID, (double)it->second.samples,setup->GetMaxCellID()+1, textSizeRel, Form("%s/SampleTOAvsCellID.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
2250 
2251       PlotSimple2D( canvas2DSigQA, hspectraTOTvsCellID, 4096, setup->GetMaxCellID()+1, textSizeRel, Form("%s/TOTvsCellID.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
2252       PlotSimple2D( canvas2DSigQA, hspectraTOAvsCellID, 1024, setup->GetMaxCellID()+1, textSizeRel, Form("%s/TOAvsCellID.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
2253       PlotSimple2D( canvas2DSigQA, hspectraADCvsCellID,  1024, setup->GetMaxCellID()+1, textSizeRel, Form("%s/ADCvsCellID.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
2254 
2255       canvas2DSigQA->SetLogz(1);
2256       PlotSimple2DZRange( canvas2DSigQA, hHighestADCAbovePedVsLayer, -10000, -10000, 0.1, 20000, textSizeRel, Form("%s/MaxADCAboveNoise_vsLayer.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, "colz", true);    
2257       
2258       for (Int_t ro = 0; ro < setup->GetNMaxROUnit()+1; ro++){
2259         for (int h = 0; h< 2; h++){      
2260             PlotSimple2D( canvas2DSigQA, h2DToAvsnSample[ro][h],(double)it->second.samples, -10000, textSizeRel,
2261                               Form("%s/ToaVsNSample_Asic_%d_Half_%d.%s", outputDirPlots.Data(), ro, h, plotSuffix.Data()), 
2262                               it->second, 1, kFALSE, "colz",true, Form("Asic %d, Half %d",ro,h));
2263             h2DWaveFormHalfAsicAll[ro][h]->GetXaxis()->SetRangeUser(-25, (it->second.samples)*25);
2264             Plot2DWithProfile( canvas2DSigQA, h2DWaveFormHalfAsicAll[ro][h], hWaveFormHalfAsicAll[ro][h], -10000, -10000, textSizeRel,
2265                               Form("%s/Waveform_Asic_%d_Half_%d.%s", outputDirPlots.Data(), ro, h, plotSuffix.Data()), 
2266                               it->second, 1, kFALSE, "colz",true, Form("Asic %d, Half %d",ro,h), -1);
2267         }
2268       }
2269 
2270       TCanvas* canvas1DSimple = new TCanvas("canvas1DSimple","",0,0,1450,1300);  // gives the page size
2271       DefaultCanvasSettings( canvas1DSimple, 0.08, 0.03, 0.03, 0.07);
2272 
2273       PlotSimple1D(canvas1DSimple, hSampleTOA, -10000, (double)it->second.samples, textSizeRel, Form("%s/NSampleToA.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1);      
2274     }
2275 
2276     Double_t maxHG = 600;
2277     Double_t maxLG = 200;
2278     // print general calib info
2279     calib.PrintGlobalInfo();  
2280     
2281     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
2282     // Multi panel plotting
2283     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++      
2284     std::cout <<"DETECTOR CONF: "<< detConf << std::endl;
2285     MultiCanvas panelPlot(detConf, "Transfer");
2286     bool init1D = panelPlot.Initialize(1);
2287     MultiCanvas panelPlot2D(detConf, "Transfer2D");
2288     bool init2D = panelPlot2D.Initialize(2);
2289     
2290     if (typeRO == ReadOut::Type::Caen) {
2291       panelPlot2D.PlotCorr2DLayer(hSpectra, 0, -20, 340, 0, 4000,
2292                                   Form("%s/LGHG2D_Corr",outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, 0, -1, skipPlotLayer );
2293       if (EventCleanup) 
2294         panelPlot2D.PlotCorr2DLayer(hSpectraTrigg, 0, -20, 340, 0, 4000,
2295                                     Form("%s/LGHG2DRejected_Corr",outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, 0, -1, skipPlotLayer );
2296       
2297     } else {
2298       panelPlot2D.PlotCorr2DLayer(hSpectra, 1, 0, it->second.samples+1, 0, 1000,
2299                                   Form("%s/Waveform",outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, 0, -1, skipPlotLayer );
2300       panelPlot2D.PlotCorr2DLayer(hSpectraTrigg, 1, 0, it->second.samples+1, 0, 1000,
2301                                   Form("%s/WaveformSignal",outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, 0, -1, skipPlotLayer );  
2302     }
2303         
2304     if (ExtPlot > 1){
2305       panelPlot.PlotNoiseWithFits(hSpectra, 0, -100, maxHG, 1.2, 
2306                                 Form("%s/SpectraWithNoiseFit_HG",outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, skipPlotLayer);
2307       if (typeRO == ReadOut::Type::Caen){
2308         panelPlot.PlotNoiseWithFits(hSpectra, 1, -20, maxLG, 1.2, 
2309                                 Form("%s/SpectraWithNoiseFit_LG",outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, skipPlotLayer);        
2310       }
2311     }
2312   }
2313   
2314   return true;
2315 } // end Analyses::TransferCalib()
2316 
2317 
2318 // ****************************************************************************
2319 // Reevaluate LGHG Corr for CAEN data
2320 // ****************************************************************************
2321 bool Analyses::ReevaluateLGHGCorr(void){
2322   std::cout<<"Reevaluate LG-HG corr for CAEN data"<<std::endl;
2323   int evts=TdataIn->GetEntries();
2324 
2325   // initialize lookup-table run list
2326   std::map<int,RunInfo> ri=readRunInfosFromFile(RunListInputName.Data(),debug,0);
2327   std::map<int,TileSpectra> hSpectra;
2328   std::map<int, TileSpectra>::iterator ithSpectra;
2329   // Find detector config
2330   DetConf::Type detConf = setup->GetDetectorConfig();
2331   
2332   // initialize calib
2333   TcalibIn->GetEntry(0);
2334   // check whether calib should be overwritten based on external text file
2335   if (OverWriteCalib){
2336     calib.ReadCalibFromTextFile(ExternalCalibFile,debug);
2337   }
2338   std::map<int,short> bcmap;
2339   std::map<int,short>::iterator bcmapIte;
2340   if (CalcBadChannel == 1)
2341     bcmap = ReadExternalBadChannelMap();
2342   
2343   // intialize run infos & reset calib object to correct run number
2344   TdataIn->GetEntry(0);     // use first event to get infos
2345   int runNr             = event.GetRunNumber();
2346   ReadOut::Type typeRO  = event.GetROtype();
2347   std::cout<< "original run numbers calib: "<<calib.GetRunNumber() << "\t" << calib.GetRunNumberPed() << "\t" << calib.GetRunNumberMip() << std::endl;
2348   calib.SetRunNumber(runNr);
2349   calib.SetBeginRunTime(event.GetBeginRunTimeAlt());
2350   std::cout<< "reset run numbers calib: "<< calib.GetRunNumber() << "\t" << calib.GetRunNumberPed() << "\t" << calib.GetRunNumberMip() << std::endl;
2351   std::map<int,RunInfo>::iterator it=ri.find(runNr);
2352 
2353   if (typeRO !=  ReadOut::Type::Caen){
2354     std::cout << "This function is not applicable for the given readout type, aborting ReevaluateLGHGCorr" << std::endl;
2355   }
2356   
2357   std::cout << "*****************************************************************" << std::endl;
2358   std::cout << "******************** Original calib *****************************" << std::endl;
2359   std::cout << "*****************************************************************" << std::endl;
2360   calib.PrintDetailedGlobalInfo();
2361   std::cout << "*****************************************************************" << std::endl;
2362   double avHGLGCorrOrg   = calib.GetAverageHGLGCorr();
2363   double avHGLGOffCorrOrg= calib.GetAverageHGLGCorrOff();
2364   double avLGHGCorrOrg   = calib.GetAverageLGHGCorr();
2365   double avLGHGOffCorrOrg= calib.GetAverageLGHGCorrOff();
2366     
2367   //==================================================================================
2368   // create additional output hist 
2369   //==================================================================================
2370   if (!CreateOutputRootHistFile()) return false;
2371 
2372   RootOutputHist->mkdir("IndividualCells");
2373   RootOutputHist->cd("IndividualCells");
2374   
2375   ROOT::Math::MinimizerOptions::SetDefaultMinimizer("Minuit2", "Migrad");  
2376   if (maxEvents == -1){
2377     maxEvents = evts;
2378   } else {
2379     std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
2380     std::cout << "ATTENTION: YOU ARE RESETTING THE MAXIMUM NUMBER OF EVENTS TO BE PROCESSED TO: " << maxEvents << ". THIS SHOULD ONLY BE USED FOR TESTING!" << std::endl;
2381     std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
2382   }
2383   
2384   if (EventCleanup == 1){
2385     std::cout << "==============================================================================" << std::endl;
2386     std::cout << "==============================================================================" << std::endl;
2387     if (calib.GetAverageScaleHigh() != -10000 ){
2388       std::cout << "resetting rejection thresholds with average HG Scale" << std::endl;
2389       cleanupLGTh   =  ((calib.GetAverageScaleHigh()-calib.GetAverageLGHGCorrOff())/calib.GetAverageLGHGCorr() )* 2.5;
2390       cleanupHGTh   =  calib.GetAverageScaleHigh()*1.5;
2391     }
2392     std::cout << "Thresholds for rejections: \t LG: " << cleanupLGTh << "\t HG: " << cleanupHGTh << std::endl;
2393     std::cout << "==============================================================================" << std::endl;
2394     std::cout << "==============================================================================" << std::endl;
2395   }
2396   int rejectedEvents  = 0;
2397 
2398   
2399   //==================================================================================
2400   // process events from tree:
2401   // - fill spectra plots for cross checking
2402   //==================================================================================
2403   for(int i=0; i<evts && i < maxEvents ; i++){
2404     if (i%5000 == 0&& i > 0 && debug > 0) std::cout << "Reading " <<  i << "/" << evts << " events"<< std::endl;
2405     if (debug > 2 && typeRO == ReadOut::Type::Hgcroc){
2406       std::cout << "************************************* NEW EVENT " << i << "  *********************************" << std::endl;
2407     }
2408     TdataIn->GetEntry(i);
2409    
2410     bool bREvent = false;
2411     if (EventCleanup == 1){
2412       if (!event.CheckEventIntegrity(calib, cleanupLGTh, cleanupHGTh)){
2413         rejectedEvents++;
2414         bREvent = true;
2415         continue;
2416       }
2417     }
2418 
2419     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2420     // process tiles in event
2421     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2422     for(int j=0; j<event.GetNTiles(); j++){
2423     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2424     // histo filling for CAEN specific things
2425     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2426       Caen* aTile=(Caen*)event.GetTile(j);
2427       ithSpectra=hSpectra.find(aTile->GetCellID());
2428       double hgCorr = aTile->GetADCHigh()-calib.GetPedestalMeanH(aTile->GetCellID());
2429       double lgCorr = aTile->GetADCLow()-calib.GetPedestalMeanL(aTile->GetCellID());
2430       // fill spectra histos
2431       if(ithSpectra!=hSpectra.end()){
2432         ithSpectra->second.FillExtCAEN(lgCorr,hgCorr, 0., 0.);
2433       } else {
2434         RootOutputHist->cd("IndividualCells");
2435         hSpectra[aTile->GetCellID()]=TileSpectra("All",2,aTile->GetCellID(),calib.GetTileCalib(aTile->GetCellID()),event.GetROtype(), nSampleHGCROCInt, debug);
2436         hSpectra[aTile->GetCellID()].FillExtCAEN(lgCorr,hgCorr, 0., 0.);
2437         RootOutput->cd();
2438       }
2439     }
2440     RootOutput->cd();
2441     // fill tree
2442     if (!bREvent) TdataOut->Fill();
2443   }
2444   // write tree
2445   TdataOut->Write();
2446   TsetupIn->CloneTree()->Write();
2447 
2448   if (EventCleanup == 1){
2449     std::cout << "****************************************************************************************************"<< std::endl; 
2450     std::cout << "****************************************************************************************************"<< std::endl; 
2451     std::cout << rejectedEvents<< "\t/" << maxEvents  << " rejected CAEN events due to corrupted data for single channels!"<< std::endl; 
2452     std::cout << "****************************************************************************************************"<< std::endl; 
2453     std::cout << "****************************************************************************************************"<< std::endl; 
2454   }
2455   
2456   //==================================================================================
2457   // Setup general plotting infos
2458   //==================================================================================  
2459   TString outputDirPlots = GetPlotOutputDir();
2460   Double_t textSizeRel = 0.035;
2461 
2462   if (CalcBadChannel > 0 || ExtPlot > 0) {
2463     gSystem->Exec("mkdir -p "+outputDirPlots);
2464     StyleSettingsBasics("pdf");
2465     SetPlotStyle();  
2466   }
2467   int maxChannelPerLayer             = (setup->GetNMaxColumn()+1)*(setup->GetNMaxRow()+1)*(setup->GetNMaxModule()+1);
2468   int maxChannelPerLayerSingleMod    = (setup->GetNMaxColumn()+1)*(setup->GetNMaxRow()+1);
2469   
2470   //==================================================================================
2471   // Application of external bad channel map
2472   //==================================================================================
2473   if (CalcBadChannel == 1 ){
2474     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
2475     // Create monitoring histos for BC extraction
2476     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
2477 
2478     // monitoring applied pedestals
2479     TH1D* hBCvsCellID      = new TH1D( "hBC_vsCellID","Bad Channel vs CellID ; cell ID; BC flag ",
2480                                               setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5);
2481     hBCvsCellID->SetDirectory(0);
2482     TH2D* hBCVsLayer   = new TH2D( "hBCVsLayer","Bad Channel Map; layer; brd channel; BC flag  ",
2483                                               setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
2484     hBCVsLayer->SetDirectory(0);
2485 
2486     int currCells = 0;
2487     if ( debug > 0 && CalcBadChannel == 1)
2488       std::cout << "============================== setting bad channel according to external map" << std::endl;
2489     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
2490     // evaluate each tile spectrum & set BC flag
2491     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
2492     for(ithSpectra=hSpectra.begin(); ithSpectra!=hSpectra.end(); ++ithSpectra){
2493       if (currCells%20 == 0 && currCells > 0 && debug > 0)
2494         std::cout << "============================== cell " <<  currCells << " / " << hSpectra.size() << " cells" << std::endl;
2495       currCells++;
2496       short bc   = 3;
2497       if ( bcmap.size() > 0 ) {
2498         bcmapIte  = bcmap.find(ithSpectra->second.GetCellID());
2499         if(bcmapIte!=bcmap.end())
2500           bc        = bcmapIte->second;
2501         else 
2502           bc        = 3;
2503       } 
2504       
2505       long cellID   = ithSpectra->second.GetCellID();
2506       ithSpectra->second.SetBadChannelInCalib(bc);
2507       
2508       // initializing pedestal fits from calib file
2509       ithSpectra->second.InitializeNoiseFitsFromCalib();
2510       
2511       // histo filling
2512       int layer     = setup->GetLayer(cellID);
2513       int chInLayer = setup->GetChannelInLayerFull(cellID,detConf);
2514       if (debug > 0 && bc > -1 && bc < 3)
2515         std::cout << "\t" << cellID << "\t" << layer << "\t" << setup->GetRow(cellID) << "\t" << setup->GetColumn(cellID)<< "\t" << setup->GetModule(cellID) << " - quality flag: " << bc << "\t" << calib.GetBadChannel(cellID) << "\t ped H: " << calib.GetPedestalMeanH(cellID) << "\t ped L: " << calib.GetPedestalMeanL(cellID)<< std::endl;
2516 
2517       hBCvsCellID->SetBinContent(hBCvsCellID->FindBin(cellID), calib.GetBadChannel(cellID));
2518       int bin2D     = hBCVsLayer->FindBin(layer,chInLayer);
2519       hBCVsLayer->SetBinContent(bin2D, calib.GetBadChannel(cellID));
2520     }
2521     
2522     hBCvsCellID->Write();
2523     hBCVsLayer->Write();
2524 
2525     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
2526     // Create canvases for channel overview plotting
2527     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
2528     // Get run info object
2529     // create directory for plot output
2530   
2531     TCanvas* canvas2DCorr = new TCanvas("canvasCorrPlots","",0,0,1450,1300);  // gives the page size
2532     DefaultCanvasSettings( canvas2DCorr, 0.08, 0.13, 0.045, 0.07);
2533 
2534     canvas2DCorr->SetLogz(0);
2535     
2536     PlotSimple2DZRange( canvas2DCorr, hBCVsLayer, -10000, -10000, -0.1, 3.1, textSizeRel, Form("%s/BadChannelMap.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, "colz", true);    
2537     calib.SetBCCalib(true);
2538   }
2539 
2540   //==================================================================================
2541   // Reevaluation of LG-HG and HG-LG factors
2542   //==================================================================================
2543   TH2D* hLGHGCorrVsLayer = new TH2D( "hLGHGCorrVsLayer","LG-HG corr; layer; brd channel; a_{LG-HG} (arb. units) ",
2544                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
2545   hLGHGCorrVsLayer->SetDirectory(0);
2546   TH2D* hLGHGCorrRatioVsLayer = new TH2D( "hLGHGCorrRatioVsLayer","LG-HG corr old/new; layer; brd channel; a_{LG-HG} (arb. units) ",
2547                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
2548   hLGHGCorrRatioVsLayer->SetDirectory(0);
2549   TH2D* hLGHGCorrOffsetVsLayer = new TH2D( "hLGHGCorrOffsetVsLayer","LG-HG corr offset; layer; brd channel; b_{LG-HG} (arb. units) ",
2550                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
2551   hLGHGCorrOffsetVsLayer->SetDirectory(0);
2552   TH2D* hLGHGCorrOffsetRatioVsLayer = new TH2D( "hLGHGCorrOffsetRatioVsLayer","LG-HG corr offset old/new; layer; brd channel; b_{LG-HG} (arb. units) ",
2553                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
2554   hLGHGCorrOffsetRatioVsLayer->SetDirectory(0);
2555   
2556   int currCells = 0;
2557   for(ithSpectra=hSpectra.begin(); ithSpectra!=hSpectra.end(); ++ithSpectra){
2558     if (currCells%20 == 0 && currCells > 0 && debug > 0)
2559       std::cout << "============================== cell " <<  currCells << " / " << hSpectra.size() << " cells" << std::endl;
2560     currCells++;
2561     long cellID   = ithSpectra->second.GetCellID();
2562     
2563     // histo filling
2564     int layer     = setup->GetLayer(cellID);
2565     int chInLayer = setup->GetChannelInLayerFull(cellID,detConf);
2566     int bin2D     = hLGHGCorrVsLayer->FindBin(layer,chInLayer);
2567 
2568     double lghgcorrB    = calib.GetLGHGCorr(cellID);
2569     double lghgcorrOffB = calib.GetLGHGCorrOff(cellID);
2570     
2571     // fitting LG-HG, HG-LG
2572     bool isGood=ithSpectra->second.FitLGHGCorr(debug,true);
2573     double lghgcorrA    = calib.GetLGHGCorr(cellID);
2574     double lghgcorrOffA = calib.GetLGHGCorrOff(cellID);
2575     
2576     // fill histos
2577     if (ithSpectra->second.GetCorrModel(0)){
2578       double ratiolghgcorr    = lghgcorrB/lghgcorrA;
2579       double ratiolghgcorrOff = lghgcorrOffB/lghgcorrOffA;
2580       hLGHGCorrVsLayer->SetBinContent(bin2D,ithSpectra->second.GetCorrModel(0)->GetParameter(1));
2581       hLGHGCorrVsLayer->SetBinError(bin2D,ithSpectra->second.GetCorrModel(0)->GetParError(1));
2582       hLGHGCorrOffsetVsLayer->SetBinContent(bin2D,ithSpectra->second.GetCorrModel(0)->GetParameter(0));
2583       hLGHGCorrOffsetVsLayer->SetBinError(bin2D,ithSpectra->second.GetCorrModel(0)->GetParError(0));
2584       hLGHGCorrRatioVsLayer->SetBinContent(bin2D,ratiolghgcorr);
2585       hLGHGCorrOffsetRatioVsLayer->SetBinContent(bin2D,ratiolghgcorrOff);      
2586     }
2587   }
2588   
2589   std::cout << "*****************************************************************" << std::endl;
2590   std::cout << "******************** Modified calib *****************************" << std::endl;
2591   std::cout << "*****************************************************************" << std::endl;
2592   calib.PrintDetailedGlobalInfo();
2593   std::cout << "*****************************************************************" << std::endl;
2594   
2595   
2596   //==================================================================================
2597   // write calib output to root-tree output file
2598   //==================================================================================  
2599   RootOutput->cd();
2600   // print calib file to text file
2601   std::cout<<"What is the value? <ped mean high>: "<<calib.GetAveragePedestalMeanHigh() << "\t good channels: " << calib.GetNumberOfChannelsWithBCflag(3) <<std::endl;
2602   if (IsCalibSaveToFile()){
2603     TString fileCalibPrint = RootOutputName;
2604     fileCalibPrint         = fileCalibPrint.ReplaceAll(".root","_calib.txt");
2605     calib.PrintCalibToFile(fileCalibPrint);
2606   }
2607   // write calib output to 
2608   TcalibOut->Fill();
2609   TcalibOut->Write();
2610   // close file
2611   RootOutput->Close();
2612 
2613   //==================================================================================
2614   // write histo output to file as cross check
2615   //==================================================================================    
2616   RootOutputHist->cd();
2617     hLGHGCorrVsLayer->Write();
2618     hLGHGCorrOffsetVsLayer->Write();
2619     hLGHGCorrRatioVsLayer->Write();
2620     hLGHGCorrOffsetRatioVsLayer->Write();
2621   // save individual cell spectra
2622   RootOutputHist->cd("IndividualCells");
2623   for(ithSpectra=hSpectra.begin(); ithSpectra!=hSpectra.end(); ++ithSpectra){
2624     ithSpectra->second.WriteExt(true);
2625   }
2626   // close root histo output file
2627   RootOutputHist->Close();
2628   // close root input file
2629   RootInput->Close();
2630   
2631   //==================================================================================
2632   // Create plots in case extended plotting is enabled for waveforms
2633   //==================================================================================
2634   if (ExtPlot > 0){
2635     double avHGLGCorr   = calib.GetAverageHGLGCorr();
2636     double avHGLGOffCorr= calib.GetAverageHGLGCorrOff();
2637     double avLGHGCorr   = calib.GetAverageLGHGCorr();
2638     double avLGHGOffCorr= calib.GetAverageLGHGCorrOff();
2639 
2640     TCanvas* canvas2DCorr = new TCanvas("canvasCorrPlots","",0,0,1450,1300);  // gives the page size
2641     DefaultCanvasSettings( canvas2DCorr, 0.08, 0.13, 0.045, 0.07);  
2642     canvas2DCorr->SetLogz(0);
2643   
2644     PlotSimple2D( canvas2DCorr, hLGHGCorrVsLayer, -10000, -10000, textSizeRel, Form("%s/LG_HG_Corr.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true, Form( "#LT a_{LGHG} #GT = %.1f", avLGHGCorr));
2645     PlotSimple2D( canvas2DCorr, hLGHGCorrOffsetVsLayer, -10000, -10000, textSizeRel, Form("%s/LG_HG_CorrOffset.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kTRUE, "colz", true, Form( "#LT b_{LGHG} #GT = %.1f", avLGHGOffCorr));
2646     PlotSimple2D( canvas2DCorr, hLGHGCorrRatioVsLayer, -10000, -10000, textSizeRel, Form("%s/LG_HG_Corr_Ratio.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true, Form( "#LT a_{LGHG} #GT = %.1f", avLGHGCorrOrg/avLGHGCorr));
2647     PlotSimple2D( canvas2DCorr, hLGHGCorrOffsetRatioVsLayer, -10000, -10000, textSizeRel, Form("%s/LG_HG_CorrOffset_Ratio.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true, Form( "#LT b_{LGHG} #GT = %.1f", avLGHGOffCorrOrg/avLGHGOffCorr));
2648     
2649     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
2650     // Multi panel plotting
2651     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++      
2652     MultiCanvas panelPlot2D(detConf, "Transfer2D");
2653     bool init2D = panelPlot2D.Initialize(2);
2654     
2655     panelPlot2D.PlotCorr2DLayer(hSpectra, 0, -20, 340, 0, 4000,
2656                                   Form("%s/LGHG2D_Corr",outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, 0, -1, skipPlotLayer );
2657   }
2658   
2659   return true;
2660 } // end Analyses::ReevaluateLGHGCorr()
2661 
2662 
2663 // ****************************************************************************
2664 // Analyse waveform
2665 // ****************************************************************************
2666 bool Analyses::VisualizeWaveform(void){
2667   std::cout<<"Visualize Waveform"<<std::endl;
2668   int evts=TdataIn->GetEntries();
2669 
2670   // Find detector config
2671   DetConf::Type detConf = setup->GetDetectorConfig();
2672 
2673   std::map<int,RunInfo> ri=readRunInfosFromFile(RunListInputName.Data(),debug,0);
2674   
2675   std::map<int,TileSpectra> hSpectra;
2676   std::map<int, TileSpectra>::iterator ithSpectra;
2677   std::map<int,TileSpectra> hSpectraTrigg;
2678   std::map<int, TileSpectra>::iterator ithSpectraTrigg;
2679   TcalibIn->GetEntry(0);
2680   
2681   // reading first event in tree to extract runnumber & RO-type
2682   TdataIn->GetEntry(0);
2683   Int_t runNr           = event.GetRunNumber();
2684   ReadOut::Type typeRO  = event.GetROtype();
2685   std::cout<< "original run numbers calib: "<<calib.GetRunNumber() << "\t" << calib.GetRunNumberPed() << "\t" << calib.GetRunNumberMip() << std::endl;
2686   calib.SetRunNumber(runNr);
2687   calib.SetBeginRunTime(event.GetBeginRunTimeAlt());
2688   std::cout<< "reset run numbers calib: "<< calib.GetRunNumber() << "\t" << calib.GetRunNumberPed() << "\t" << calib.GetRunNumberMip() << std::endl;
2689 
2690   if (typeRO != ReadOut::Type::Hgcroc){
2691     std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
2692     std::cout << "This routine is not meant to run on CAEN data! Please check you are loading the correct inputs! \n ABORTING!!!" << std::endl;
2693     std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
2694     return false; 
2695   }
2696   
2697   //==================================================================================
2698   // create additional output hist
2699   //==================================================================================
2700   if (!CreateOutputRootHistFile()) return false;
2701   
2702   RootOutputHist->mkdir("IndividualCells");
2703   RootOutputHist->mkdir("IndividualCellsTrigg");
2704   RootOutputHist->cd("IndividualCells");
2705   
2706   ROOT::Math::MinimizerOptions::SetDefaultMinimizer("Minuit2", "Migrad");  
2707   if (maxEvents == -1){
2708     maxEvents = evts;
2709   } else {
2710     std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
2711     std::cout << "ATTENTION: YOU ARE RESETTING THE MAXIMUM NUMBER OF EVENTS TO BE PROCESSED TO: " << maxEvents << ". THIS SHOULD ONLY BE USED FOR TESTING!" << std::endl;
2712     std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
2713   }
2714   
2715   //==================================================================================
2716   // setup waveform builder for HGCROC data
2717   //==================================================================================
2718   waveform_fit_base *waveform_builder = nullptr;
2719   if (GetHGCROCOptInteg() == 1 || GetHGCROCOptInteg() == 101 ){
2720     waveform_builder = new max_sample_fit_n_integ(GetHGCROCNSampleInteg());
2721   } else {
2722     waveform_builder = new max_sample_fit();
2723   }
2724   
2725   //==================================================================================
2726   // process events from tree
2727   //==================================================================================
2728   for(int i=0; i<evts && i < maxEvents ; i++){
2729     if (i%5000 == 0&& i > 0 && debug > 0) std::cout << "Reading " <<  i << "/" << evts << " events"<< std::endl;
2730     if (debug > 2 ){
2731       std::cout << "************************************* NEW EVENT " << i << "  *********************************" << std::endl;
2732     }
2733     TdataIn->GetEntry(i);   
2734     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2735     // process tiles in event
2736     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++    
2737     for(int j=0; j<event.GetNTiles(); j++){
2738       //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
2739       // histo filling for HGCROC specific things 
2740       //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++        
2741       Hgcroc* aTile=(Hgcroc*)event.GetTile(j);
2742       int cellID = aTile->GetCellID();
2743       ithSpectra=hSpectra.find(cellID);
2744       ithSpectraTrigg=hSpectraTrigg.find(cellID);
2745       
2746       //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
2747       // possibly reevaluate waveform
2748       //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
2749       if (GetHGCROCOptInteg() > 99){
2750         // pedestals
2751         double ped    = calib.GetPedestalMeanL(cellID);
2752         double pedErr = calib.GetPedestalSigL(cellID);
2753         if (ped == -1000){
2754           ped     = calib.GetPedestalMeanH(cellID);
2755           pedErr  = calib.GetPedestalSigH(cellID);
2756           if (ped == -1000){
2757             ped     = aTile->GetPedestal();
2758             pedErr  = 5;
2759           }
2760         }
2761         // reevaluate waveform
2762         waveform_builder->set_waveform(aTile->GetADCWaveform());
2763         waveform_builder->fit_with_average_ped(ped);
2764         aTile->SetIntegratedADC(waveform_builder->get_E());
2765         aTile->SetPedestal(waveform_builder->get_pedestal());
2766       }
2767       
2768       // obtain integrated tile quantities for histo filling
2769       double adc = aTile->GetIntegratedADC();
2770       double tot = aTile->GetRawTOT();
2771       double toa = aTile->GetRawTOA();
2772       // obtain samples in which TOA, TOT, maximum ADC are firing
2773       Int_t nSampTOA    = aTile->GetCorrectedFirstTOASample(calib.GetToAOff(cellID));        
2774       Int_t nOffEmpty   = 2;
2775       
2776       // fill spectra histos
2777       if(ithSpectra!=hSpectra.end()){
2778         ithSpectra->second.FillExtHGCROC(adc,toa,tot,nSampTOA,-1);
2779         ithSpectra->second.FillWaveformVsTime(aTile->GetADCWaveform(), aTile->GetCorrectedTOA(), calib.GetPedestalMeanH(cellID),nOffEmpty);
2780       } else {
2781         RootOutputHist->cd("IndividualCells");
2782         hSpectra[cellID]=TileSpectra("full",3,cellID,calib.GetTileCalib(cellID),event.GetROtype(), nSampleHGCROCInt, debug);
2783         hSpectra[cellID].FillExtHGCROC(adc,toa,tot,nSampTOA,-1);
2784         hSpectra[cellID].FillWaveformVsTime(aTile->GetADCWaveform(), aTile->GetCorrectedTOA(), calib.GetPedestalMeanH(cellID),nOffEmpty);
2785       }
2786       // fill spectra histos for signals with ToA
2787       if (toa > 0 ){      // needed for summing tests
2788         if(ithSpectraTrigg!=hSpectraTrigg.end()){
2789           ithSpectraTrigg->second.FillExtHGCROC(adc,toa,tot,nSampTOA,-1);
2790           ithSpectraTrigg->second.FillWaveformVsTime(aTile->GetADCWaveform(), aTile->GetCorrectedTOA(), calib.GetPedestalMeanH(cellID),nOffEmpty);
2791         } else {
2792           RootOutputHist->cd("IndividualCellsTrigg");
2793           hSpectraTrigg[cellID]=TileSpectra("signal",3,cellID,calib.GetTileCalib(cellID),event.GetROtype(), nSampleHGCROCInt, debug);
2794           hSpectraTrigg[cellID].FillExtHGCROC(adc,toa,tot,nSampTOA,-1);
2795           hSpectraTrigg[cellID].FillWaveformVsTime(aTile->GetADCWaveform(), aTile->GetCorrectedTOA(), calib.GetPedestalMeanH(cellID),nOffEmpty);
2796         }
2797       }
2798     }
2799   }
2800 
2801   //==================================================================================
2802   // Setup general plotting infos
2803   //==================================================================================    
2804   std::map<int,RunInfo>::iterator it=ri.find(runNr);
2805   TString outputDirPlots = GetPlotOutputDir();
2806   Double_t textSizeRel = 0.035;
2807 
2808   gSystem->Exec("mkdir -p "+outputDirPlots);
2809   StyleSettingsBasics("pdf");
2810   SetPlotStyle();  
2811   
2812   // print general calib info
2813   calib.PrintGlobalInfo();  
2814 
2815   //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
2816   // plot single layers 
2817   //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
2818   MultiCanvas panelPlot(detConf, "VisuWave");
2819   bool init1D = panelPlot.Initialize(1);
2820   MultiCanvas panelPlot2D(detConf, "VisuWave2D");
2821   bool init2D = panelPlot2D.Initialize(2);
2822     
2823   panelPlot2D.PlotCorr2DLayer(hSpectra, 1, -25000, (it->second.samples)*25000, 0, 300,
2824                               Form("%s/Waveform",outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, 0, -1, skipPlotLayer  );
2825   panelPlot2D.PlotCorr2DLayer(hSpectra, 2, 0, 1024, 0, 300,
2826                               Form("%s/TOA_ADC",outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, 0, -1, skipPlotLayer );
2827   panelPlot2D.PlotCorr2DLayer(hSpectra, 3, 0, 1024, 0, it->second.samples,
2828                               Form("%s/TOA_Sample",outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, 0, -1, skipPlotLayer );
2829   panelPlot2D.PlotCorr2DLayer(hSpectraTrigg, 1, -25000, (it->second.samples)*25000, 0, 300,
2830                               Form("%s/WaveformSignal",outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, 0, -1, skipPlotLayer );
2831   panelPlot2D.PlotCorr2DLayer(hSpectraTrigg, 2, 0, 1024, 0, 300,
2832                               Form("%s/TOA_ADC_Signal",outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, 0, -1, skipPlotLayer );
2833   panelPlot2D.PlotCorr2DLayer(hSpectraTrigg, 3, 0, 1024, 0, it->second.samples,
2834                               Form("%s/TOA_Sample_Signal",outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, 0, -1, skipPlotLayer );
2835   if (ExtPlot > 1){
2836     panelPlot.PlotSpectra( hSpectra, 0, -100, 1024, 1.2, 
2837                            Form("%s/Spectra_ADC" ,outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, skipPlotLayer);
2838     panelPlot.PlotSpectra( hSpectra, 3, 0, 1024, 1.2, 
2839                            Form("%s/TOA" ,outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, skipPlotLayer);
2840     panelPlot.PlotSpectra( hSpectra, 4, 0, 4096, 1.2, 
2841                            Form("%s/TOT" ,outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, skipPlotLayer);
2842   }
2843   
2844   //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
2845   // store individual histogram outputs
2846   //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
2847   RootOutputHist->cd();
2848   RootOutputHist->cd("IndividualCells");
2849   for(ithSpectra=hSpectra.begin(); ithSpectra!=hSpectra.end(); ++ithSpectra){
2850     ithSpectra->second.WriteExt(true);
2851   }
2852   RootOutputHist->cd("IndividualCellsTrigg");
2853   if (typeRO == ReadOut::Type::Hgcroc){
2854     for(ithSpectraTrigg=hSpectraTrigg.begin(); ithSpectraTrigg!=hSpectraTrigg.end(); ++ithSpectraTrigg){
2855       ithSpectraTrigg->second.WriteExt(true);
2856     }
2857   }
2858   RootInput->Close();
2859   return true;
2860 } // end Analyses::VisualizeWaveform()
2861 
2862 //***********************************************************************************************
2863 //*********************** intial scaling calculation function *********************************
2864 //***********************************************************************************************
2865 bool Analyses::GetScaling(void){ 
2866   std::cout<<"GetScaling"<<std::endl;
2867   auto start = std::chrono::steady_clock::now();
2868   
2869   std::map<int,RunInfo> ri=readRunInfosFromFile(RunListInputName.Data(),debug,0);
2870   
2871   std::map<int,TileSpectra> hSpectra;
2872   std::map<int,TileSpectra> hSpectraTrigg;
2873   std::map<int, TileSpectra>::iterator ithSpectra;
2874   std::map<int, TileSpectra>::iterator ithSpectraTrigg;
2875 
2876   ROOT::Math::MinimizerOptions::SetDefaultMinimizer("Minuit2", "Migrad");  
2877   if (!CreateOutputRootHistFile()) return false;
2878 
2879   // reading calib from file
2880   TcalibIn->GetEntry(0);
2881   // check whether calib should be overwritten based on external text file
2882   if (OverWriteCalib){
2883     calib.ReadCalibFromTextFile(ExternalCalibFile,debug);
2884   }
2885   
2886   // reading first event in tree to extract runnumber & RO-type
2887   TdataIn->GetEntry(0);
2888   int evts=TdataIn->GetEntries();
2889   Int_t runNr           = event.GetRunNumber();
2890   ReadOut::Type typeRO  = event.GetROtype();
2891   std::cout<< "Total number of events: " << evts << std::endl;
2892   std::cout<< "original run numbers calib: "<<calib.GetRunNumber() << "\t" << calib.GetRunNumberPed() << "\t" << calib.GetRunNumberMip() << std::endl;
2893   // reseting run numbers for Mip calib
2894   calib.SetRunNumberMip(runNr);
2895   calib.SetBeginRunTimeMip(event.GetBeginRunTimeAlt());
2896   std::cout<< "reset run numbers calib: "<< calib.GetRunNumber() << "\t" << calib.GetRunNumberPed() << "\t" << calib.GetRunNumberMip() << std::endl;  // Get run info object
2897   std::map<int,RunInfo>::iterator it=ri.find(runNr);
2898   // set year of data taking in case adjustments are necessary
2899   SetYear(it->second.year);
2900   
2901   
2902   
2903   // find detector config
2904   DetConf::Type detConf   = setup->GetDetectorConfig();
2905   
2906   //==================================================================================
2907   // setup waveform builder for HGCROC data
2908   //==================================================================================
2909   waveform_fit_base *waveform_builder = nullptr;
2910   if (GetHGCROCOptInteg() == 1 || GetHGCROCOptInteg() == 101){
2911     waveform_builder = new max_sample_fit_n_integ(GetHGCROCNSampleInteg());
2912   } else {
2913     waveform_builder = new max_sample_fit();
2914   }
2915   
2916   //==================================================================================
2917   // first pass over tree to extract spectra 
2918   //==================================================================================
2919   // entering histoOutput file
2920   RootOutputHist->mkdir("IndividualCells");
2921   RootOutputHist->cd("IndividualCells");
2922 
2923   if (maxEvents == -1){
2924     maxEvents = evts;
2925   } else {
2926     std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
2927     std::cout << "ATTENTION: YOU ARE RESETTING THE MAXIMUM NUMBER OF EVENTS TO BE PROCESSED TO: " << maxEvents << ". THIS SHOULD ONLY BE USED FOR TESTING!" << std::endl;
2928     std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
2929   }
2930   // set debug frequency
2931   int evtDeb = 5000;
2932   if (typeRO != ReadOut::Type::Caen)
2933     evtDeb = 2500;
2934   
2935   for(int i=0; i<evts && i < maxEvents; i++){ // GetScaling() first pass through tree
2936     TdataIn->GetEntry(i);
2937     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2938     // reset calib object info 
2939     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2940     if (i%evtDeb == 0 && i > 0 && debug > 0){
2941       auto end = std::chrono::steady_clock::now();
2942       auto duration = std::chrono::duration_cast<std::chrono::seconds>(end - start);
2943       std::cout << "Step 0: Reading " <<  i << " / " << evts << " events"  << " duration: " << duration.count() << " seconds"<< std::endl;
2944     }
2945     if (i == 0 && debug > 2) std::cout << "decoding cell IDs" << std::endl ;
2946     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2947     // process tiles in event
2948     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2949     for(int j=0; j<event.GetNTiles(); j++){ // loop over tiles in event
2950       //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2951       // CAEN treatment
2952       //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++      
2953       if (typeRO == ReadOut::Type::Caen) {
2954         Caen* aTile=(Caen*)event.GetTile(j);
2955         if (i == 0 && debug > 2) std::cout << ((TString)setup->DecodeCellID(aTile->GetCellID())).Data() << std::endl;
2956         
2957         ithSpectra=hSpectra.find(aTile->GetCellID());
2958         double hgCorr = aTile->GetADCHigh()-calib.GetPedestalMeanH(aTile->GetCellID());
2959         double lgCorr = aTile->GetADCLow()-calib.GetPedestalMeanL(aTile->GetCellID());
2960         
2961         // fill spectra histos    
2962         if(ithSpectra!=hSpectra.end()){
2963           ithSpectra->second.FillSpectraCAEN(lgCorr,hgCorr);
2964           if (hgCorr > 3*calib.GetPedestalSigH(aTile->GetCellID()) && lgCorr > 3*calib.GetPedestalSigL(aTile->GetCellID()) && hgCorr < 3900 )
2965             ithSpectra->second.FillCorrCAEN(lgCorr,hgCorr);
2966         } else {
2967           RootOutputHist->cd("IndividualCells");
2968           hSpectra[aTile->GetCellID()]=TileSpectra("mip1st",aTile->GetCellID(),calib.GetTileCalib(aTile->GetCellID()),event.GetROtype(), nSampleHGCROCInt, debug);
2969           hSpectra[aTile->GetCellID()].FillSpectraCAEN(lgCorr,hgCorr);;
2970           if (hgCorr > 3*calib.GetPedestalSigH(aTile->GetCellID()) && lgCorr > 3*calib.GetPedestalSigL(aTile->GetCellID() && hgCorr < 3900) )
2971             hSpectra[aTile->GetCellID()].FillCorrCAEN(lgCorr,hgCorr);
2972           RootOutput->cd();
2973         }
2974       //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2975       // HGCROC treatment
2976       //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2977       } else if (typeRO == ReadOut::Type::Hgcroc) { 
2978         Hgcroc* aTile=(Hgcroc*)event.GetTile(j);
2979         if (i == 0 && debug > 2) std::cout << ((TString)setup->DecodeCellID(aTile->GetCellID())).Data() << std::endl;
2980         long cellID = aTile->GetCellID();
2981         
2982         //-------------------------------------------------------------------------------
2983         // possibly reevaluate waveform
2984         //-------------------------------------------------------------------------------
2985         if (GetHGCROCOptInteg() > 99){
2986           // pedestals
2987           double ped    = calib.GetPedestalMeanL(cellID);
2988           double pedErr = calib.GetPedestalSigL(cellID);
2989           if (ped == -1000){
2990             ped     = calib.GetPedestalMeanH(cellID);
2991             pedErr  = calib.GetPedestalSigH(cellID);
2992             if (ped == -1000){
2993               ped     = aTile->GetPedestal();
2994               pedErr  = 5;
2995             }
2996           }
2997           // reevaluate waveform
2998           waveform_builder->set_waveform(aTile->GetADCWaveform());
2999           waveform_builder->fit_with_average_ped(ped);
3000           aTile->SetIntegratedADC(waveform_builder->get_E());
3001           aTile->SetPedestal(waveform_builder->get_pedestal());
3002         }
3003         
3004         ithSpectra=hSpectra.find(cellID);
3005         double adc = aTile->GetIntegratedADC();        
3006         double tot = aTile->GetRawTOT();
3007         double toa = aTile->GetRawTOA();
3008 
3009         // for CalibSummary:
3010         // get voltage for the run (Setup?) event.GetVop()
3011         // run number is runNr
3012         
3013         // fill spectra histos    
3014         if(ithSpectra!=hSpectra.end()){
3015           ithSpectra->second.FillHGCROC(adc,toa,tot);
3016         } else {
3017           RootOutputHist->cd("IndividualCells");
3018           hSpectra[cellID]=TileSpectra("mip1st",cellID,calib.GetTileCalib(cellID),event.GetROtype(), nSampleHGCROCInt, debug);
3019           hSpectra[cellID].FillHGCROC(adc,toa,tot);
3020           RootOutput->cd();
3021         }
3022         
3023       } // end HGCROC treatment
3024     } // end loop over tiles in event 
3025     RootOutput->cd();
3026   } // GetScaling() end first pass through tree (loop over events)
3027   // TdataOut->Write();
3028   TsetupIn->CloneTree()->Write();
3029   
3030   RootOutputHist->cd();
3031  
3032   //==================================================================================
3033   // Monitoring histos for calib parameters & fits results of 1st iteration 
3034   //==================================================================================
3035   int maxChannelPerLayer             = (setup->GetNMaxColumn()+1)*(setup->GetNMaxRow()+1)*(setup->GetNMaxModule()+1);
3036   int maxChannelPerLayerSingleMod    = (setup->GetNMaxColumn()+1)*(setup->GetNMaxRow()+1);
3037 
3038   // monitoring applied pedestals
3039   TH1D* hMeanPedHGvsCellID      = new TH1D( "hMeanPedHG_vsCellID","mean Ped High Gain vs CellID ; cell ID; #mu_{noise, HG} (arb. units) ",
3040                                             setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5);
3041   hMeanPedHGvsCellID->SetDirectory(0);
3042   TH1D* hMeanPedHG              = new TH1D( "hMeanPedHG","mean Ped High Gain ; #mu_{noise, HG} (arb. units); counts ",
3043                                             500, -0.5, 500-0.5);
3044   hMeanPedHG->SetDirectory(0);
3045   TH2D* hspectraHGMeanVsLayer   = new TH2D( "hspectraHGMeanVsLayer","Mean Ped High Gain; layer; brd channel; #mu_{Ped HG} (arb. units) ",
3046                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
3047   hspectraHGMeanVsLayer->SetDirectory(0);
3048   TH2D* hspectraHGSigmaVsLayer  = new TH2D( "hspectraHGSigmaVsLayer","Sigma Ped High Gain; layer; brd channel; #sigma_{Ped HG} (arb. units) ",
3049                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
3050   hspectraHGSigmaVsLayer->SetDirectory(0);
3051   TH1D* hMeanPedLGvsCellID      = new TH1D( "hMeanPedLG_vsCellID","mean Ped Low Gain vs CellID ; cell ID; #mu_{noise, LG} (arb. units) ",
3052                                             setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5);
3053   hMeanPedLGvsCellID->SetDirectory(0);
3054   TH1D* hMeanPedLG             = new TH1D( "hMeanPedLG","mean Ped Low Gain ; #mu_{noise, LG} (arb. units); counts ",
3055                                             500, -0.5, 500-0.5);
3056   hMeanPedLG->SetDirectory(0);
3057   TH2D* hspectraLGMeanVsLayer   = new TH2D( "hspectraLGMeanVsLayer","Mean Ped Low Gain; layer; brd channel; #mu_{PED LG} (arb. units) ",
3058                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
3059   hspectraLGMeanVsLayer->SetDirectory(0);
3060   TH2D* hspectraLGSigmaVsLayer  = new TH2D( "hspectraLGSigmaVsLayer","Sigma Ped Low Gain; layer; brd channel; #sigma_{Ped LG} (arb. units)",
3061                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
3062   hspectraLGSigmaVsLayer->SetDirectory(0);
3063   // monitoring 1st iteration mip fits
3064   TH2D* hspectraHGMaxVsLayer1st   = new TH2D( "hspectraHGMaxVsLayer_1st","Max High Gain; layer; brd channel; Max_{HG, 1^{st}} (arb. units) ",
3065                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
3066   hspectraHGMaxVsLayer1st->SetDirectory(0);
3067   TH2D* hspectraHGFWHMVsLayer1st   = new TH2D( "hspectraHGFWHMVsLayer_1st","FWHM High Gain; layer; brd channel; FWHM_{HG, 1^{st}} (arb. units) ",
3068                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
3069   hspectraHGFWHMVsLayer1st->SetDirectory(0);
3070   TH2D* hspectraHGLMPVVsLayer1st   = new TH2D( "hspectraHGLMPVVsLayer_1st","MPV High Gain; layer; brd channel; MPV_{HG, 1^{st}} (arb. units) ",
3071                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
3072   hspectraHGLMPVVsLayer1st->SetDirectory(0);
3073   TH2D* hspectraHGLSigmaVsLayer1st = new TH2D( "hspectraHGLSigmaVsLayer_1st","Sigma Landau High Gain; layer; brd channel; #sigma_{L,HG, 1^{st}} (arb. units) ",
3074                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
3075   hspectraHGLSigmaVsLayer1st->SetDirectory(0);
3076   TH2D* hspectraHGGSigmaVsLayer1st = new TH2D( "hspectraHGGSigmaVsLayer_1st","Sigma Gauss High Gain; layer; brd channel; #sigma_{G,HG, 1^{st}} (arb. units) ",
3077                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
3078   hspectraHGGSigmaVsLayer1st->SetDirectory(0);
3079   TH2D* hLGHGCorrVsLayer = new TH2D( "hLGHGCorrVsLayer","LG-HG corr; layer; brd channel; a_{LG-HG} (arb. units) ",
3080                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
3081   hLGHGCorrVsLayer->SetDirectory(0);
3082   TH2D* hHGLGCorrVsLayer = new TH2D( "hHGLGCorrVsLayer","HG-LG corr; layer; brd channel; a_{HG-LG} (arb. units) ",
3083                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
3084   hHGLGCorrVsLayer->SetDirectory(0);
3085   TH2D* hLGHGCorrOffsetVsLayer = new TH2D( "hLGHGCorrOffsetVsLayer","LG-HG corr offset; layer; brd channel; b_{LG-HG} (arb. units) ",
3086                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
3087   hLGHGCorrOffsetVsLayer->SetDirectory(0);
3088   TH2D* hHGLGCorrOffsetVsLayer = new TH2D( "hHGLGCorrVsLayer","HG-LG corr offset; layer; brd channel; b_{HG-LG} (arb. units) ",
3089                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
3090   hHGLGCorrOffsetVsLayer->SetDirectory(0);
3091   
3092   TH1D* hMaxHG1st             = new TH1D( "hMaxHG1st","Max High Gain ;Max_{HG, 1^{st}} (arb. units) ; counts ",
3093                                             2000, -0.5, 2000-0.5);
3094   hMaxHG1st->SetDirectory(0);
3095   TH1D* hLGHGCorr             = new TH1D( "hLGHGCorr","LG-HG corr ; a_{LG-HG} (arb. units) ; counts ",
3096                                             400, -20, 20);
3097   hLGHGCorr->SetDirectory(0);
3098   TH1D* hHGLGCorr             = new TH1D( "hHGLGCorr","LG-HG corr ; a_{HG-LG} (arb. units) ; counts ",
3099                                             400, -1., 1.);
3100   hHGLGCorr->SetDirectory(0);
3101 
3102   TH1D* hNPosTrigg            = new TH1D( "hNPosTrigg","Positions triggered ;# Pos_{trig} (arb. units) ; counts ", 
3103                                           maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
3104   hNPosTrigg->SetDirectory(0);
3105   
3106   
3107   // fit pedestal
3108   double* parameters    = new double[6];
3109   double* parErrAndRes  = new double[6];
3110   bool isGood;
3111   int currCells = 0;
3112   if ( debug > 0)
3113     std::cout << "============================== starting fitting 1st iteration" << std::endl;
3114   //==================================================================================
3115   // 1st iteration of fitting of individual cell spectra
3116   //==================================================================================
3117   for(ithSpectra=hSpectra.begin(); ithSpectra!=hSpectra.end(); ++ithSpectra){ // 1st iteration, loop through spectra
3118     if (currCells%20 == 0 && currCells > 0 && debug > 0)
3119       std::cout << "============================== cell " <<  currCells << " / " << hSpectra.size() << " cells" << std::endl;
3120     currCells++;
3121     // reset parameters & errors
3122     for (int p = 0; p < 6; p++){
3123       parameters[p]   = 0;
3124       parErrAndRes[p] = 0;
3125     }
3126     // fit MIP for CAEN HG/ HGCROC ADC
3127     isGood        = ithSpectra->second.FitMipHG(parameters, parErrAndRes, debug, yearData, false, calib.GetVov(), 1);
3128     
3129     // fill cross-check histos
3130     long cellID   = ithSpectra->second.GetCellID();
3131     int layer     = setup->GetLayer(cellID);
3132     int chInLayer = setup->GetChannelInLayerFull(cellID, detConf);
3133     hMeanPedHGvsCellID->SetBinContent(hMeanPedHGvsCellID->FindBin(cellID), calib.GetPedestalMeanH(cellID));
3134     hMeanPedLGvsCellID->SetBinContent(hMeanPedLGvsCellID->FindBin(cellID), calib.GetPedestalMeanL(cellID));
3135     hMeanPedHG->Fill(calib.GetPedestalMeanH(cellID));
3136     hMeanPedLG->Fill(calib.GetPedestalMeanL(cellID));
3137     
3138     int bin2D     = hspectraHGMeanVsLayer->FindBin(layer,chInLayer);
3139     hspectraHGMeanVsLayer->SetBinContent(bin2D, calib.GetPedestalMeanH(cellID));
3140     hspectraHGSigmaVsLayer->SetBinContent(bin2D, calib.GetPedestalSigH(cellID));
3141     hspectraLGMeanVsLayer->SetBinContent(bin2D, calib.GetPedestalMeanL(cellID));
3142     hspectraLGSigmaVsLayer->SetBinContent(bin2D, calib.GetPedestalSigL(cellID));
3143 
3144     if (isGood){
3145       // get uncertainty on HG Max
3146       double rel_err_L_MPV = parErrAndRes[1]/parameters[1]; // Landau MPV error / MPV
3147       double sigma_Max = rel_err_L_MPV * parameters[4]; // relative MPV err * Max ADC value
3148       hspectraHGMaxVsLayer1st->SetBinContent(bin2D, parameters[4]);
3149       hspectraHGMaxVsLayer1st->SetBinError(bin2D, sigma_Max);
3150       hspectraHGFWHMVsLayer1st->SetBinContent(bin2D, parameters[5]);
3151       hspectraHGLMPVVsLayer1st->SetBinContent(bin2D, parameters[1]);
3152       hspectraHGLMPVVsLayer1st->SetBinError(bin2D, parErrAndRes[1]);
3153       hspectraHGLSigmaVsLayer1st->SetBinContent(bin2D, parameters[0]);
3154       hspectraHGLSigmaVsLayer1st->SetBinError(bin2D, parErrAndRes[0]);
3155       hspectraHGGSigmaVsLayer1st->SetBinContent(bin2D, parameters[3]);
3156       hspectraHGGSigmaVsLayer1st->SetBinError(bin2D, parErrAndRes[3]);
3157       
3158       hMaxHG1st->Fill(parameters[4]);
3159     }
3160     
3161     // fit correlation LG-HG, HG-LG for CAEN data and fill histograms
3162     if (typeRO == ReadOut::Type::Caen) {
3163       // fitting LG-HG, HG-LG
3164       isGood=ithSpectra->second.FitCorrCAEN(debug);
3165       // fill histos
3166       if (ithSpectra->second.GetCorrModel(0)){
3167         hLGHGCorrVsLayer->SetBinContent(bin2D,ithSpectra->second.GetCorrModel(0)->GetParameter(1));
3168         hLGHGCorrVsLayer->SetBinError(bin2D,ithSpectra->second.GetCorrModel(0)->GetParError(1));
3169         hLGHGCorrOffsetVsLayer->SetBinContent(bin2D,ithSpectra->second.GetCorrModel(0)->GetParameter(0));
3170         hLGHGCorrOffsetVsLayer->SetBinError(bin2D,ithSpectra->second.GetCorrModel(0)->GetParError(0));
3171         hLGHGCorr->Fill(ithSpectra->second.GetCorrModel(0)->GetParameter(1));
3172       } 
3173       if (ithSpectra->second.GetCorrModel(1)){
3174         hHGLGCorrVsLayer->SetBinContent(bin2D,ithSpectra->second.GetCorrModel(1)->GetParameter(1));
3175         hHGLGCorrVsLayer->SetBinError(bin2D,ithSpectra->second.GetCorrModel(1)->GetParError(1));    
3176         hHGLGCorrOffsetVsLayer->SetBinContent(bin2D,ithSpectra->second.GetCorrModel(1)->GetParameter(0));
3177         hHGLGCorrOffsetVsLayer->SetBinError(bin2D,ithSpectra->second.GetCorrModel(1)->GetParError(0));    
3178         hHGLGCorr->Fill(ithSpectra->second.GetCorrModel(1)->GetParameter(1));
3179       }
3180     }
3181   } // end loop over spectra for 1st fitting iteration
3182   if ( debug > 0)
3183     std::cout << "============================== done fitting 1st iteration" << std::endl;
3184 
3185   //==================================================================================
3186   // setup additional monitoring histos
3187   //==================================================================================  
3188   TH1D* hHGTileSum[100]; // ATTENTION this array needs to be large enough to fit an entire plane 
3189   for (int c = 0; c < maxChannelPerLayer; c++ ){
3190     hHGTileSum[c] = new TH1D( Form("hHGTileSum_absChB%d",c),"av ADC surrounding cells ; ADC (arb. units); counts ",
3191                               4000, -0.5, 4000-0.5);
3192     hHGTileSum[c]->SetDirectory(0);
3193   }
3194   
3195   //==================================================================================
3196   // setup trigger sel & general selection parameters
3197   //==================================================================================
3198   TRandom3* rand    = new TRandom3();
3199   Int_t localTriggerTiles = 4;
3200   double factorMinTrigg   = 0.5;
3201   double factorMaxTrigg   = 4.;
3202   if (typeRO == ReadOut::Type::Caen){
3203     if (yearData == 2023){
3204       localTriggerTiles = 6;
3205       factorMaxTrigg    = 3.;
3206     }
3207   } else if (typeRO == ReadOut::Type::Hgcroc){
3208     localTriggerTiles = 6;
3209     factorMinTrigg    = 0.3;
3210   }
3211   
3212   RootOutputHist->mkdir("IndividualCellsTrigg");
3213   RootOutputHist->cd("IndividualCellsTrigg");  
3214   //==================================================================================
3215   // first fitting for each cell
3216   //==================================================================================
3217   int actCh1st = 0; 
3218   double averageScale = calib.GetAverageScaleHigh(actCh1st);
3219   int actChIalt                  = 0;
3220   double averageNTilesI          = 0.;
3221   double averageScalePerTile     = calib.GetAverageScaleHighPerSingleLayer(actChIalt, averageNTilesI);
3222   
3223   double meanPedSign  = calib.GetAveragePedestalSigHigh();
3224   double meanFWHMHG   = calib.GetAverageScaleWidthHigh();
3225   double avHGLGCorr   = calib.GetAverageHGLGCorr();
3226   double avHGLGOffCorr= calib.GetAverageHGLGCorrOff();
3227   double avLGHGCorr   = calib.GetAverageLGHGCorr();
3228   double avLGHGOffCorr= calib.GetAverageLGHGCorrOff();
3229   if (typeRO == ReadOut::Type::Caen){
3230     std::cout << "average HG mip: " << averageScale << "\t active ch: "<< actCh1st<< std::endl;
3231   } else {
3232     std::cout << "average mip: " << averageScale << " per tile mip: "<< averageScalePerTile << "\t act. ch: "<< actCh1st << "\t av tiles/seg "<< averageNTilesI << std::endl;
3233   }
3234   
3235   std::map<int,int> mapNActiveLayers;
3236   std::map<int,double> chargeTotChInLayer;
3237   
3238   for (int k = 0; k < maxChannelPerLayer;k++){
3239     mapNActiveLayers[k] = 0;
3240   }
3241   int eventsNoClearTrigg = 0;
3242   
3243   for(int i=0; i<evts && i < maxEvents; i++){ // loop over events
3244     TdataIn->GetEntry(i);
3245     if (i%evtDeb == 0 && i > 0 && debug > 0){
3246       auto end = std::chrono::steady_clock::now();
3247       auto duration = std::chrono::duration_cast<std::chrono::seconds>(end - start);
3248       std::cout << "1st step: Reading " <<  i << " / " << evts << " events"  << " duration: " << duration.count() << " seconds"<< std::endl;
3249     }
3250 
3251     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3252     // find likely trigger region
3253     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3254     // CAEN column pre selection
3255     if (typeRO == ReadOut::Type::Caen) {
3256       for (int k = 0; k < maxChannelPerLayer;k++){
3257         chargeTotChInLayer[k] = 0;
3258       }
3259       for(int j=0; j<event.GetNTiles(); j++){
3260         Caen* aTile=(Caen*)event.GetTile(j);
3261         double hgCorr = aTile->GetADCHigh()-calib.GetPedestalMeanH(aTile->GetCellID());
3262         int chInLayer   = setup->GetChannelInLayerFull(aTile->GetCellID(), detConf);
3263         if (i == 0){
3264           if (calib.GetBCCalib()){
3265             if(calib.GetBadChannel(aTile->GetCellID())>1) 
3266               mapNActiveLayers[chInLayer]= mapNActiveLayers[chInLayer]+1;
3267           } else {
3268             mapNActiveLayers[chInLayer]= mapNActiveLayers[chInLayer]+1;
3269           }
3270         }
3271         if (calib.GetBCCalib() && calib.GetBadChannel(aTile->GetCellID())>1){
3272           chargeTotChInLayer[chInLayer] = chargeTotChInLayer[chInLayer]+hgCorr;
3273         } else if (!calib.GetBCCalib()){
3274           chargeTotChInLayer[chInLayer] = chargeTotChInLayer[chInLayer]+hgCorr;
3275         }
3276       }
3277       int nPosTrigg  = 0;
3278       for (int k = 0; k < maxChannelPerLayer;k++){
3279         chargeTotChInLayer[k] = chargeTotChInLayer[k]/(double)mapNActiveLayers[k];
3280         if (chargeTotChInLayer[k] > minFracTriggThre* meanPedSign)
3281           nPosTrigg++;
3282       }
3283       hNPosTrigg->Fill(nPosTrigg);
3284       if (nPosTrigg == 0){
3285         continue;
3286         eventsNoClearTrigg++;
3287       }  
3288     // HGCROC column pre selection
3289     } else if (typeRO == ReadOut::Type::Hgcroc) {
3290       for (int k = 0; k < maxChannelPerLayer;k++){
3291         chargeTotChInLayer[k] = 0;
3292       }
3293       for(int j=0; j<event.GetNTiles(); j++){
3294         Hgcroc* aTile=(Hgcroc*)event.GetTile(j);
3295         double adc      = aTile->GetIntegratedADC();
3296         int chInLayer   = setup->GetChannelInLayerFull(aTile->GetCellID(), detConf);
3297         if (i == 0){
3298           if (calib.GetBCCalib()){
3299             if(calib.GetBadChannel(aTile->GetCellID())>1) 
3300               mapNActiveLayers[chInLayer]= mapNActiveLayers[chInLayer]+1;
3301           } else {
3302             mapNActiveLayers[chInLayer]= mapNActiveLayers[chInLayer]+1;
3303           }
3304         }
3305         if (calib.GetBCCalib() && calib.GetBadChannel(aTile->GetCellID())>1){
3306           chargeTotChInLayer[chInLayer] = chargeTotChInLayer[chInLayer]+adc;
3307         } else if (!calib.GetBCCalib()){
3308           chargeTotChInLayer[chInLayer] = chargeTotChInLayer[chInLayer]+adc;
3309         }
3310       }
3311       int nPosTrigg  = 0;
3312       for (int k = 0; k < maxChannelPerLayer;k++){
3313         chargeTotChInLayer[k] = chargeTotChInLayer[k]/(double)mapNActiveLayers[k];
3314         if (chargeTotChInLayer[k] > minFracTriggThre* meanPedSign)
3315           nPosTrigg++;
3316       }
3317       hNPosTrigg->Fill(nPosTrigg);
3318       if (nPosTrigg == 0){
3319         continue;
3320         eventsNoClearTrigg++;
3321       }
3322     }
3323     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3324     // process tiles in event
3325     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++    
3326     for(int j=0; j<event.GetNTiles(); j++){
3327       //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3328       // histo filling for CAEN specific things
3329       //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++      
3330       if (typeRO == ReadOut::Type::Caen) {
3331         Caen* aTile=(Caen*)event.GetTile(j);
3332         if (i == 0 && debug > 2) std::cout << ((TString)setup->DecodeCellID(aTile->GetCellID())).Data() << std::endl;
3333         long currCellID = aTile->GetCellID();
3334         int chInLayer       = setup->GetChannelInLayerFull(currCellID, detConf);
3335         double triggPrim    = -50.;
3336         bool localMuonTrigg = false;
3337 
3338         // read current tile
3339         ithSpectraTrigg=hSpectraTrigg.find(currCellID);
3340         double hgCorr = aTile->GetADCHigh()-calib.GetPedestalMeanH(currCellID);
3341         double lgCorr = aTile->GetADCLow()-calib.GetPedestalMeanL(currCellID);
3342 
3343         if (chargeTotChInLayer[chInLayer] > minFracTriggThre* meanPedSign){
3344           triggPrim = event.CalculateLocalMuonTrigg(calib, rand, currCellID, localTriggerTiles, avLGHGCorr, 2);
3345           aTile->SetLocalTriggerPrimitive(triggPrim);
3346           localMuonTrigg = event.InspectIfLocalMuonTrigg(currCellID, averageScalePerTile, factorMinTrigg, factorMaxTrigg);
3347         } else {
3348           aTile->SetLocalTriggerPrimitive(triggPrim);
3349         }
3350         
3351         if (triggPrim != -50.){
3352           hHGTileSum[chInLayer]->Fill(aTile->GetLocalTriggerPrimitive());
3353           
3354           if(ithSpectraTrigg!=hSpectraTrigg.end()){
3355             ithSpectraTrigg->second.FillTrigger(aTile->GetLocalTriggerPrimitive());
3356           } else {
3357             RootOutputHist->cd("IndividualCellsTrigg");
3358             hSpectraTrigg[currCellID]=TileSpectra("mipTrigg",currCellID,calib.GetTileCalib(currCellID),event.GetROtype(), nSampleHGCROCInt, debug);
3359             hSpectraTrigg[currCellID].FillTrigger(aTile->GetLocalTriggerPrimitive());;
3360             RootOutput->cd();
3361           }
3362           // only fill tile spectra if 4 surrounding tiles on average are compatible with muon response
3363           if (localMuonTrigg){
3364             aTile->SetLocalTriggerBit(1);
3365             ithSpectraTrigg=hSpectraTrigg.find(currCellID);
3366             ithSpectraTrigg->second.FillSpectraCAEN(lgCorr,hgCorr);
3367             if (hgCorr > 3*calib.GetPedestalSigH(currCellID) && lgCorr > 3*calib.GetPedestalSigL(currCellID) && hgCorr < 3900 )
3368               ithSpectraTrigg->second.FillCorrCAEN(lgCorr,hgCorr);
3369           }
3370         }
3371         
3372       //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
3373       // histo filling for HGCROC specific things & resetting of ped
3374       //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++        
3375       } else if (typeRO == ReadOut::Type::Hgcroc) {
3376         Hgcroc* aTile=(Hgcroc*)event.GetTile(j);
3377         if (i == 0 && debug > 2) std::cout << ((TString)setup->DecodeCellID(aTile->GetCellID())).Data() << std::endl;
3378         long currCellID = aTile->GetCellID();
3379       
3380         //-------------------------------------------------------------------------------
3381         // possibly reevaluate waveform
3382         //-------------------------------------------------------------------------------
3383         if (GetHGCROCOptInteg() > 99){
3384           // pedestals
3385           double ped    = calib.GetPedestalMeanL(currCellID);
3386           double pedErr = calib.GetPedestalSigL(currCellID);
3387           if (ped == -1000){
3388             ped     = calib.GetPedestalMeanH(currCellID);
3389             pedErr  = calib.GetPedestalSigH(currCellID);
3390             if (ped == -1000){
3391               ped     = aTile->GetPedestal();
3392               pedErr  = 5;
3393             }
3394           }
3395           // reevaluate waveform
3396           waveform_builder->set_waveform(aTile->GetADCWaveform());
3397           waveform_builder->fit_with_average_ped(ped);
3398           aTile->SetIntegratedADC(waveform_builder->get_E());
3399           aTile->SetPedestal(waveform_builder->get_pedestal());
3400         }
3401         
3402         
3403         ithSpectraTrigg=hSpectraTrigg.find(aTile->GetCellID());
3404         // double adc = aTile->GetPedestal()+aTile->GetIntegratedADC();
3405         double adc = aTile->GetIntegratedADC();
3406         double tot = aTile->GetRawTOT();
3407         double toa = aTile->GetRawTOA();
3408         int chInLayer       = setup->GetChannelInLayerFull(currCellID, detConf);
3409         double triggPrim    = -50.;
3410         bool localMuonTrigg = false;
3411         if (chargeTotChInLayer[chInLayer] > minFracTriggThre* meanPedSign){
3412           triggPrim = event.CalculateLocalMuonTrigg(calib, rand, currCellID, localTriggerTiles, 0., 0);
3413           aTile->SetLocalTriggerPrimitive(triggPrim);
3414           localMuonTrigg = event.InspectIfLocalMuonTrigg(currCellID, averageScalePerTile, factorMinTrigg, factorMaxTrigg);
3415         } else {
3416           aTile->SetLocalTriggerPrimitive(triggPrim);
3417         }
3418         // estimate local muon trigger
3419         if (triggPrim != -50.){
3420           hHGTileSum[chInLayer]->Fill(aTile->GetLocalTriggerPrimitive());
3421         
3422           if(ithSpectraTrigg!=hSpectraTrigg.end()){
3423             ithSpectraTrigg->second.FillTrigger(aTile->GetLocalTriggerPrimitive());
3424           } else {
3425             RootOutputHist->cd("IndividualCellsTrigg");
3426             hSpectraTrigg[currCellID]=TileSpectra("mipTrigg",currCellID,calib.GetTileCalib(currCellID),event.GetROtype(),nSampleHGCROCInt, debug);
3427             hSpectraTrigg[currCellID].FillTrigger(aTile->GetLocalTriggerPrimitive());;
3428             RootOutput->cd();
3429           }
3430           // only fill tile spectra if 4 surrounding tiles on average are compatible with muon response
3431           if (localMuonTrigg){
3432             aTile->SetLocalTriggerBit(1);
3433             ithSpectraTrigg=hSpectraTrigg.find(aTile->GetCellID());
3434             ithSpectraTrigg->second.FillHGCROC(adc,toa,tot);
3435             
3436           }
3437         }
3438       }
3439     }
3440     RootOutput->cd();
3441     TdataOut->Fill();
3442   } // end loop over events
3443   TdataOut->Write();
3444   
3445   if (eventsNoClearTrigg > 0){
3446       std::cout << "*********************************************************" << std::endl;
3447       std::cout << "SKIPPED " << eventsNoClearTrigg << " as no clear trigger present" << std::endl;
3448       std::cout << "*********************************************************" << std::endl;
3449   }
3450   
3451   //==================================================================================
3452   // Monitoring histos for fits results of 2nd iteration 
3453   //==================================================================================
3454   RootOutputHist->cd();
3455   
3456   // monitoring trigger 
3457   TH2D* hmipTriggers              = new TH2D( "hmipTriggers","muon triggers; layer; brd channel; counts ",
3458                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
3459   hmipTriggers->SetDirectory(0);
3460   TH2D* hSuppresionNoise          = new TH2D( "hSuppresionNoise","S/B noise region; layer; brd channel; S/B noise region",
3461                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
3462   hSuppresionNoise->SetDirectory(0);
3463   TH2D* hSuppresionSignal         = new TH2D( "hSuppresionSignal","S/B signal region; layer; brd channel; S/B signal region",
3464                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
3465   hSuppresionSignal->SetDirectory(0);
3466 
3467   // monitoring 2nd iteration mip fits
3468   TH2D* hspectraHGMaxVsLayer2nd   = new TH2D( "hspectraHGMaxVsLayer_2nd","Max High Gain; layer; brd channel; Max_{HG, 2^{nd}} (arb. units) ",
3469                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
3470   hspectraHGMaxVsLayer2nd->SetDirectory(0);
3471   TH2D* hspectraHGFWHMVsLayer2nd   = new TH2D( "hspectraHGFWHMVsLayer_2nd","FWHM High Gain; layer; brd channel; FWHM_{HG, 2^{nd}} (arb. units) ",
3472                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
3473   hspectraHGFWHMVsLayer2nd->SetDirectory(0);
3474   TH2D* hspectraHGLMPVVsLayer2nd   = new TH2D( "hspectraHGLMPVVsLayer_2nd","MPV High Gain; layer; brd channel; MPV_{HG, 2^{nd}} (arb. units) ",
3475                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
3476   hspectraHGLMPVVsLayer2nd->SetDirectory(0);
3477   TH2D* hspectraHGLSigmaVsLayer2nd = new TH2D( "hspectraHGLSigmaVsLayer_2nd","Sigma Landau High Gain; layer; brd channel; #sigma_{L,HG, 2^{nd}} (arb. units) ",
3478                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
3479   hspectraHGLSigmaVsLayer2nd->SetDirectory(0);
3480   TH2D* hspectraHGGSigmaVsLayer2nd = new TH2D( "hspectraHGGSigmaVsLayer_2nd","Sigma Gauss High Gain; layer; brd channel; #sigma_{G,HG, 2^{nd}} (arb. units) ",
3481                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
3482   hspectraHGGSigmaVsLayer2nd->SetDirectory(0);
3483   TH2D* hspectraLGMaxVsLayer2nd   = new TH2D( "hspectraLGMaxVsLayer_2nd","Max High Gain; layer; brd channel; Max_{LG, 2^{nd}} (arb. units) ",
3484                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
3485   hspectraLGMaxVsLayer2nd->SetDirectory(0);
3486   TH2D* hspectraLGFWHMVsLayer2nd   = new TH2D( "hspectraLGFWHMVsLayer_2nd","FWHM High Gain; layer; brd channel; FWHM_{LG, 2^{nd}} (arb. units) ",
3487                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
3488   hspectraLGFWHMVsLayer2nd->SetDirectory(0);
3489   TH2D* hspectraLGLMPVVsLayer2nd   = new TH2D( "hspectraLGLMPVVsLayer_2nd","MPV High Gain; layer; brd channel; MPV_{LG, 2^{nd}} (arb. units) ",
3490                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
3491   hspectraLGLMPVVsLayer2nd->SetDirectory(0);
3492   TH2D* hspectraLGLSigmaVsLayer2nd = new TH2D( "hspectraLGLSigmaVsLayer_2nd","Sigma Landau High Gain; layer; brd channel; #sigma_{L,LG, 2^{nd}} (arb. units) ",
3493                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
3494   hspectraLGLSigmaVsLayer2nd->SetDirectory(0);
3495   TH2D* hspectraLGGSigmaVsLayer2nd = new TH2D( "hspectraLGGSigmaVsLayer_2nd","Sigma Gauss High Gain; layer; brd channel; #sigma_{G,LG, 2^{nd}} (arb. units) ",
3496                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
3497   hspectraLGGSigmaVsLayer2nd->SetDirectory(0);
3498 
3499   TH1D* hMaxHG2nd             = new TH1D( "hMaxHG2nd","Max High Gain ;Max_{HG, 2^{nd}} (arb. units) ; counts ",
3500                                             2000, -0.5, 2000-0.5);
3501   hMaxHG2nd->SetDirectory(0);
3502   TH1D* hMaxLG2nd             = new TH1D( "hMaxLG2nd","Max High Gain ;Max_{LG, 2^{nd}} (arb. units) ; counts ",
3503                                             400, -0.5, 400-0.5);
3504   hMaxLG2nd->SetDirectory(0);
3505 
3506   TH2D* hHGscaleChi2VsLayer = new TH2D( "hHGscaleChi2VsLayer", "HG MiP fit #chi^{2}/NDF; layer; brd channel; #chi^{2}/ndf ",    
3507   setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5); // -EP
3508   hHGscaleChi2VsLayer->SetDirectory(0); 
3509 
3510   TH2D* hSNRTriggVsLayer = new TH2D( "hSNRTriggVsLayer", "HG Triggered S/N; layers; brd channel; SNR ",
3511                                 setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5); // -EP
3512   hSNRTriggVsLayer->SetDirectory(0);
3513 
3514   //TH2D* hChi2VsNMipTrigg = new TH2D( "hChi2VsNMipTrigg", "HG MIP fit by stats; Number of MIP triggers; #chi^{2}/ndf; ", 50, 0, 10000, 80, 0, 20); // -EP
3515   //hChi2VsNMipTrigg->SetDirectory(0);
3516 
3517   // 2D beam profile -EP    
3518   int absMaxCols = setup->GetAbsMaxColumnsSetup(detConf);
3519   int absMaxRows = setup->GetAbsMaxRowsSetup(detConf);
3520   std::cout << "Outer dimensions: " << std::endl;
3521   std::cout << "\t x: " << setup->GetMinX() << " - " << setup->GetMaxX() << "\t" << setup->GetAbsMaxColumnsSetup(detConf)<< std::endl;
3522   std::cout << "\t y: " << setup->GetMinY() << " - " << setup->GetMaxY() << "\t" << setup->GetAbsMaxRowsSetup(detConf)<< std::endl;
3523   std::cout << "\t z: " << setup->GetMinZ() << " - " << setup->GetMaxZ() << "\t" << setup->GetNMaxLayer()+1<< std::endl;
3524     
3525   int thisbinxmax = setup->GetNMaxColumn()+1;   
3526   int thisbinymax = (int)(setup->GetNMaxRow()+1)*(setup->GetNMaxModule()+1);
3527   TH2D* hMipTriggXY = new TH2D( "hMipTriggXY", "MIP Triggers summed over layers; X (col); Y (row); Num triggers", absMaxCols, -0.5, absMaxCols-0.5, absMaxRows, -0.5, absMaxRows-0.5);
3528   hMipTriggXY->SetDirectory(0);
3529 
3530   // 3D beam profile -EP
3531   int absMaxLayers = (int)setup->GetNMaxLayer()+1;
3532   TH3D *hMipTriggXYZ = new TH3D( "hMipTriggXYZ", "MIP Triggers; X (col); Z (layer); Y (row); Num triggers", absMaxCols, -0.5, absMaxCols-0.5, absMaxLayers, -0.5, absMaxLayers-0.5, absMaxRows, -0.5, absMaxRows-0.5);
3533   hMipTriggXYZ->SetDirectory(0);
3534 
3535   TH2D* hMPVvsNoisePeak = new TH2D( "hMPVvsNoisePeak", "Signal to noise peak ADC; noise peak (ADC); MiP MPV (ADC); ", 20, -5, 10, 20, 0, 50); // -EP
3536   hMPVvsNoisePeak->SetDirectory(0);
3537 
3538   //TH1D* hPeakSeparation = new TH1D("hPeakSeparation", "Signal-noise peak separation; MPV - noise peak (ADC); counts", 35, 0, 35); // -EP
3539   //hPeakSeparation->SetDirectory(0);
3540 
3541 
3542   //==================================================================================
3543   // Fitting 2nd iteration for mip fits
3544   //==================================================================================
3545   currCells = 0;
3546   if ( debug > 0)
3547     std::cout << "============================== starting fitting 2nd iteration" << std::endl;
3548   
3549   // define CalibSummary object for this run -EP
3550   CalibSummary tileSum = CalibSummary(calib.GetRunNumber(), calib.GetRunNumber(), calib.GetVop(), it->second.pdg );
3551   tileSum.SetLabel(tileSum.GetLabelLegend( it->second,  0));
3552   
3553   for(ithSpectraTrigg=hSpectraTrigg.begin(); ithSpectraTrigg!=hSpectraTrigg.end(); ++ithSpectraTrigg){ // loop over spectra for 2nd iteration
3554     if (currCells%20 == 0 && currCells > 0 && debug > 0)
3555       std::cout << "============================== cell " <<  currCells << " / " << hSpectraTrigg.size() << " cells" << std::endl;
3556     currCells++;
3557     // reset parameters & errors
3558     for (int p = 0; p < 6; p++){
3559       parameters[p]   = 0;
3560       parErrAndRes[p] = 0;
3561     }
3562     // fit MIP for CAEN HG/ HGCROC ADC 
3563     isGood=ithSpectraTrigg->second.FitMipHG(parameters, parErrAndRes, debug, yearData, false, calib.GetVov(), averageScale);
3564 
3565     long cellID = ithSpectraTrigg->second.GetCellID();
3566     tileSum.Fill(ithSpectraTrigg->second.GetCalib()); // fill tileSum with this tile's TileCalib -EP
3567 
3568     // fill cross-check histos
3569     double redChi2  = parErrAndRes[4] / parErrAndRes[5]; // chi2/ndf
3570     int layer       = setup->GetLayer(cellID);
3571     int chInLayer   = setup->GetChannelInLayerFull(cellID, detConf);
3572     int row                 = setup->GetRow(cellID);
3573     int col                 = setup->GetColumn(cellID);
3574     int mod                 = setup->GetModule(cellID);
3575     int bin2D       = hspectraHGMeanVsLayer->FindBin(layer,chInLayer);
3576     
3577     double pedSigHG = calib.GetPedestalSigH(cellID);
3578     double maxBin   = 0;
3579     if (typeRO == ReadOut::Type::Caen){ 
3580       maxBin   = 3800;
3581     } else {
3582       maxBin   = 1024;
3583     }
3584 
3585     
3586     Int_t binNLow   = ithSpectraTrigg->second.GetHG()->FindBin(-1*pedSigHG);
3587     Int_t binNHigh  = ithSpectraTrigg->second.GetHG()->FindBin(3*pedSigHG);
3588     Int_t binSHigh  = ithSpectraTrigg->second.GetHG()->FindBin(maxBin);
3589     
3590     double S_NoiseR = ithSpectraTrigg->second.GetHG()->Integral(binNLow, binNHigh);
3591     double S_SigR   = ithSpectraTrigg->second.GetHG()->Integral(binNHigh, binSHigh);
3592     
3593     ithSpectra      = hSpectra.find(cellID);
3594     double B_NoiseR = ithSpectra->second.GetHG()->Integral(binNLow , binNHigh);
3595     double B_SigR   = ithSpectra->second.GetHG()->Integral(binNHigh, binSHigh);
3596     
3597     double SB_NoiseR  = (B_NoiseR != 0.) ? S_NoiseR/B_NoiseR : 0;
3598     double SB_SigR    = (B_SigR != 0.) ? S_SigR/B_SigR : 0;
3599     
3600     double SNR_trigg = (S_NoiseR != 0.) ? S_SigR/S_NoiseR : 0;
3601 
3602     hmipTriggers->SetBinContent(bin2D, ithSpectraTrigg->second.GetHG()->GetEntries());
3603     hSuppresionNoise->SetBinContent(bin2D, SB_NoiseR);
3604     hSuppresionSignal->SetBinContent(bin2D, SB_SigR);
3605     hSNRTriggVsLayer->SetBinContent(bin2D, SNR_trigg);
3606 
3607     // get 2D and 3D beam profiles 
3608     int thisbinx = setup->GetAbsColumn(cellID, detConf)+1; // the +1s are due to the 0th bin in root being underflow
3609     int thisbiny = setup->GetAbsRow(cellID, detConf) +1;
3610     int thisbinz = layer + 1;
3611 
3612     int numMipTrig = ithSpectraTrigg->second.GetHG()->GetEntries();
3613     hMipTriggXY->SetBinContent(thisbinx, thisbiny, hMipTriggXY->GetBinContent(thisbinx, thisbiny) + numMipTrig);
3614     hMipTriggXYZ->SetBinContent(thisbinx, thisbinz, thisbiny, numMipTrig);
3615 
3616     // estimate separation between noise and mip peaks
3617     //double peaksep = parameters[1]-ithSpectraTrigg->second.GetMaxXInRangeHG(-1*pedSigHG, 3*pedSigHG); 
3618 
3619     if (isGood){
3620       // get uncertainty on HG Max
3621       double rel_err_L_MPV = parErrAndRes[1]/parameters[1]; // Landau MPV error / MPV
3622       double sigma_Max = rel_err_L_MPV * parameters[4]; // relative MPV err * Max ADC value
3623       hspectraHGMaxVsLayer2nd->SetBinContent(bin2D, parameters[4]);
3624       hspectraHGMaxVsLayer2nd->SetBinError(bin2D, sigma_Max);
3625       hMPVvsNoisePeak->Fill(ithSpectraTrigg->second.GetMaxXInRangeHG(-1*pedSigHG, 3*pedSigHG), parameters[1]);
3626       hHGscaleChi2VsLayer->SetBinContent(bin2D, redChi2);   
3627       hspectraHGFWHMVsLayer2nd->SetBinContent(bin2D, parameters[5]);
3628       hspectraHGLMPVVsLayer2nd->SetBinContent(bin2D, parameters[1]);
3629       hspectraHGLMPVVsLayer2nd->SetBinError(bin2D, parErrAndRes[1]);
3630       hspectraHGLSigmaVsLayer2nd->SetBinContent(bin2D, parameters[0]);
3631       hspectraHGLSigmaVsLayer2nd->SetBinError(bin2D, parErrAndRes[0]);
3632       hspectraHGGSigmaVsLayer2nd->SetBinContent(bin2D, parameters[3]);
3633       hspectraHGGSigmaVsLayer2nd->SetBinError(bin2D, parErrAndRes[3]);
3634       hMaxHG2nd->Fill(parameters[4]);
3635     }
3636     // fit MIP for CAEN LG
3637     if (typeRO == ReadOut::Type::Caen) {
3638       // reset parameters & errors
3639       for (int p = 0; p < 6; p++){
3640         parameters[p]   = 0;
3641         parErrAndRes[p] = 0;
3642       }
3643       // fit MIP for CAEN LG
3644       isGood=ithSpectraTrigg->second.FitMipLG(parameters, parErrAndRes, debug, yearData, false, calib.GetVov(),1);
3645       /// fill cross-check histos
3646       if (isGood){
3647         hspectraLGMaxVsLayer2nd->SetBinContent(bin2D, parameters[4]);
3648         hspectraLGFWHMVsLayer2nd->SetBinContent(bin2D, parameters[5]);
3649         hspectraLGLMPVVsLayer2nd->SetBinContent(bin2D, parameters[1]);
3650         hspectraLGLMPVVsLayer2nd->SetBinError(bin2D, parErrAndRes[1]);
3651         hspectraLGLSigmaVsLayer2nd->SetBinContent(bin2D, parameters[0]);
3652         hspectraLGLSigmaVsLayer2nd->SetBinError(bin2D, parErrAndRes[0]);
3653         hspectraLGGSigmaVsLayer2nd->SetBinContent(bin2D, parameters[3]);
3654         hspectraLGGSigmaVsLayer2nd->SetBinError(bin2D, parErrAndRes[3]);
3655         hMaxLG2nd->Fill(parameters[4]);
3656       }
3657     }
3658   } // end loop over spectra that passed trigger selection (2nd iteration)
3659   if ( debug > 0)
3660     std::cout << "============================== done fitting 2nd iteration" << std::endl;
3661   
3662   //==================================================================================
3663   // Summarize fitting success & average scales
3664   //==================================================================================    
3665   int actCh2nd = 0;
3666   double averageScaleUpdated    = calib.GetAverageScaleHigh(actCh2nd);
3667   
3668   int actChAalt                  = 0;
3669   double averageNTilesA          = 0.;
3670   double averageScaleUpPerTile   = calib.GetAverageScaleHighPerSingleLayer(actChAalt, averageNTilesA);
3671 
3672   
3673   double meanFWHMHGUpdated      = calib.GetAverageScaleWidthHigh();
3674   double averageScaleLowUpdated = 0.;
3675   double meanFWHMLGUpdated      = 0.;
3676   if (typeRO == ReadOut::Type::Caen){
3677     averageScaleLowUpdated = calib.GetAverageScaleLow();
3678     meanFWHMLGUpdated      = calib.GetAverageScaleWidthLow();
3679   }
3680   
3681   if (typeRO == ReadOut::Type::Caen) {
3682     std::cout << "average 1st iteration HG mip: " << averageScale << "\t act. channels: " <<   actCh1st << std::endl;
3683     std::cout << "average 2nd iteration  HG mip: " << averageScaleUpdated << "\t LG mip: " << averageScaleLowUpdated << "\t act. channels: " <<   actCh2nd << std::endl;
3684   } else {
3685     std::cout << "average input mip: " << averageScale << " per tile mip: "<< averageScalePerTile << "\t act. ch: "<< actCh1st << "\t av tiles/seg "<< averageNTilesI << std::endl;
3686     std::cout << "average updated mip: " << averageScaleUpdated << " per tile mip: "<< averageScaleUpPerTile << "\t act. ch: "<< actCh2nd<< "\t av tiles/seg "<< averageNTilesA << std::endl;    
3687   }
3688   RootOutput->cd();
3689   
3690   if (IsCalibSaveToFile()){
3691     TString fileCalibPrint = RootOutputName;
3692     fileCalibPrint         = fileCalibPrint.ReplaceAll(".root","_calib.txt");
3693     calib.PrintCalibToFile(fileCalibPrint);
3694   }
3695 
3696   //==================================================================================
3697   // Write tree objects and calibs to tree output root file
3698   //==================================================================================
3699   TcalibOut->Fill();
3700   TcalibOut->Write();
3701   // close tree output root file
3702   RootOutput->Close();
3703 
3704   //==================================================================================
3705   // Write histos to histo output root file
3706   //==================================================================================
3707   // write spectra for individual cells
3708   RootOutputHist->cd("IndividualCells");
3709     for(ithSpectra=hSpectra.begin(); ithSpectra!=hSpectra.end(); ++ithSpectra){
3710       ithSpectra->second.Write(true);
3711     }
3712   // write spectra for individual cells with trigger requirement
3713   RootOutputHist->cd("IndividualCellsTrigg");
3714     for(ithSpectra=hSpectraTrigg.begin(); ithSpectra!=hSpectraTrigg.end(); ++ithSpectra){
3715       ithSpectra->second.Write(true);
3716     }
3717   // write summary histograms
3718   RootOutputHist->cd();
3719     hMeanPedHGvsCellID->Write();
3720     hMeanPedHG->Write();
3721     hNPosTrigg->Write();
3722     
3723     hspectraHGMeanVsLayer->Write();
3724     hspectraHGSigmaVsLayer->Write();
3725     hspectraHGMaxVsLayer1st->Write();
3726     hspectraHGFWHMVsLayer1st->Write();
3727     hspectraHGLMPVVsLayer1st->Write();
3728     hspectraHGLSigmaVsLayer1st->Write();
3729     hspectraHGGSigmaVsLayer1st->Write();
3730     hMaxHG1st->Write();
3731     
3732     
3733     hspectraHGMaxVsLayer2nd->Write();
3734     hspectraHGFWHMVsLayer2nd->Write();
3735     hspectraHGLMPVVsLayer2nd->Write();
3736     hspectraHGLSigmaVsLayer2nd->Write();
3737     hspectraHGGSigmaVsLayer2nd->Write();
3738     hMaxHG2nd->Write();
3739 
3740     hHGscaleChi2VsLayer->Write();
3741     //hChi2VsNMipTrigg->Write();    
3742     hMPVvsNoisePeak->Write();
3743     hSNRTriggVsLayer->Write();
3744     //hPeakSeparation->Write();
3745     hMipTriggXY->Write();
3746     hMipTriggXYZ->Write();
3747     // CAEN specific histos
3748     if (typeRO == ReadOut::Type::Caen) {
3749       hMeanPedLGvsCellID->Write();
3750       hMeanPedLG->Write();
3751       hspectraLGMeanVsLayer->Write();
3752       hspectraLGSigmaVsLayer->Write();
3753       hLGHGCorrVsLayer->Write();
3754       hLGHGCorrOffsetVsLayer->Write();
3755       hHGLGCorrVsLayer->Write();
3756       hHGLGCorrOffsetVsLayer->Write();
3757       hLGHGCorr->Write();
3758       hHGLGCorr->Write();
3759       hspectraLGMaxVsLayer2nd->Write();
3760       hspectraLGFWHMVsLayer2nd->Write();
3761       hspectraLGLMPVVsLayer2nd->Write();
3762       hspectraLGLSigmaVsLayer2nd->Write();
3763       hspectraLGGSigmaVsLayer2nd->Write();
3764       hMaxLG2nd->Write();
3765     }
3766     // trigger effectiveness summary histos
3767     for (int c = 0; c< maxChannelPerLayer; c++)
3768       if (hHGTileSum[c]) hHGTileSum[c]->Write();
3769     hmipTriggers->Write();
3770     hSuppresionNoise->Write();
3771     hSuppresionSignal->Write();
3772   // fill calib tree & write it
3773   // close open root files
3774   RootOutputHist->Write();
3775   RootOutputHist->Close();
3776   // close input root file
3777   RootInput->Close();
3778 
3779   //==================================================================================
3780   // Set up general plotting variables
3781   //==================================================================================    
3782   // create directory for plot output
3783   TString outputDirPlots = GetPlotOutputDir();
3784   gSystem->Exec("mkdir -p "+outputDirPlots);
3785   
3786   
3787   Double_t textSizeRel = 0.035;
3788   StyleSettingsBasics("pdf");
3789   SetPlotStyle();
3790   //==================================================================================
3791   // Create canvases for channel overview plotting
3792   //==================================================================================
3793   TCanvas* canvas1DSimple = new TCanvas("canvas1DSimple","",0,0,1450,1300);  // gives the page size
3794   DefaultCanvasSettings( canvas1DSimple, 0.08, 0.03, 0.03, 0.07);
3795   PlotSimple1D(canvas1DSimple, hNPosTrigg, -10000, maxChannelPerLayer, textSizeRel, Form("%s/NPosTriggers.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1);        
3796 
3797 
3798   TCanvas* canvas2DCorr = new TCanvas("canvasCorrPlots","",0,0,1450,1300);  // gives the page size
3799   DefaultCanvasSettings( canvas2DCorr, 0.08, 0.13, 0.045, 0.07);  
3800   canvas2DCorr->SetLogz(0);
3801   PlotSimple2D( canvas2DCorr, hspectraHGMeanVsLayer, -10000, -10000, textSizeRel, Form("%s/HG_NoiseMean.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
3802   PlotSimple2D( canvas2DCorr, hspectraHGSigmaVsLayer,-10000, -10000, textSizeRel, Form("%s/HG_NoiseSigma.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1,  kFALSE, "colz", true);
3803   PlotSimple2D( canvas2DCorr, hspectraHGMaxVsLayer1st, -10000, -10000, textSizeRel, Form("%s/HG_MaxMip_1st.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true, Form( "#LT Max_{HG} #GT = %.1f", averageScale));
3804   PlotSimple2D( canvas2DCorr, hspectraHGFWHMVsLayer1st, -10000, -10000, textSizeRel, Form("%s/HG_FWHMMip_1st.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true, Form( "#LT FWHM_{HG} #GT = %.1f", meanFWHMHG));
3805   PlotSimple2D( canvas2DCorr, hspectraHGLMPVVsLayer1st, -10000, -10000, textSizeRel, Form("%s/HG_LandMPVMip_1st.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
3806   PlotSimple2D( canvas2DCorr, hspectraHGLSigmaVsLayer1st, -10000, -10000, textSizeRel, Form("%s/HG_LandSigMip_1st.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
3807   PlotSimple2D( canvas2DCorr, hspectraHGGSigmaVsLayer1st, -10000, -10000, textSizeRel, Form("%s/HG_GaussSigMip_1st.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
3808   PlotSimple2D( canvas2DCorr, hspectraHGMaxVsLayer2nd, -10000, -10000, textSizeRel, Form("%s/HG_MaxMip_2nd.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true, Form( "#LT Max_{HG} #GT = %.1f", averageScaleUpdated));
3809   PlotSimple2D( canvas2DCorr, hspectraHGFWHMVsLayer2nd, -10000, -10000, textSizeRel, Form("%s/HG_FWHMMip_2nd.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true, Form( "#LT FWHM_{HG} #GT = %.1f", meanFWHMHGUpdated));
3810   PlotSimple2D( canvas2DCorr, hspectraHGLMPVVsLayer2nd, -10000, -10000, textSizeRel, Form("%s/HG_LandMPVMip_2nd.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
3811   PlotSimple2D( canvas2DCorr, hspectraHGLSigmaVsLayer2nd, -10000, -10000, textSizeRel, Form("%s/HG_LandSigMip_2nd.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
3812   PlotSimple2D( canvas2DCorr, hspectraHGGSigmaVsLayer2nd, -10000, -10000, textSizeRel, Form("%s/HG_GaussSigMip_2nd.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
3813   PlotSimple2D( canvas2DCorr, hSNRTriggVsLayer, -10000, -10000, textSizeRel, Form("%s/SNRTriggVsLayer.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
3814   PlotSimple2D( canvas2DCorr, hHGscaleChi2VsLayer, -10000, -10000, textSizeRel, Form("%s/HGscaleChi2VsLayer.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
3815   PlotSimple2D( canvas2DCorr, hMipTriggXY, -10000, -10000, textSizeRel, Form("%s/MipTriggXY.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
3816   canvas2DCorr->SetLogz(1);
3817   TString drawOpt = "colz";
3818   if (yearData == 2023)
3819     drawOpt = "colz,text";
3820   PlotSimple2D( canvas2DCorr, hmipTriggers, -10000, -10000, textSizeRel, Form("%s/MuonTriggers.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, drawOpt, true, Form( "evt. collected = %d", evts));
3821   PlotSimple2D( canvas2DCorr, hSuppresionNoise, -10000, -10000, textSizeRel, Form("%s/SuppressionNoise.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, drawOpt, true);
3822   PlotSimple2D( canvas2DCorr, hSuppresionSignal, -10000, -10000, textSizeRel, Form("%s/SuppressionSignal.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, drawOpt, true);
3823   
3824   canvas2DCorr->SetLogz(0);
3825   
3826   if (typeRO == ReadOut::Type::Caen) {
3827     PlotSimple2D( canvas2DCorr, hspectraLGMeanVsLayer, -10000, -10000, textSizeRel, Form("%s/LG_NoiseMean.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
3828     PlotSimple2D( canvas2DCorr, hspectraLGSigmaVsLayer, -10000, -10000, textSizeRel, Form("%s/LG_NoiseSigma.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
3829     PlotSimple2D( canvas2DCorr, hspectraLGMaxVsLayer2nd, -10000, -10000, textSizeRel, Form("%s/LG_MaxMip_2nd.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true, Form( "#LT Max_{LG} #GT = %.1f", averageScaleLowUpdated));
3830     PlotSimple2D( canvas2DCorr, hspectraLGFWHMVsLayer2nd, -10000, -10000, textSizeRel, Form("%s/LG_FWHMMip_2nd.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true, Form( "#LT FWHM_{LG} #GT = %.1f", meanFWHMLGUpdated));
3831     PlotSimple2D( canvas2DCorr, hspectraLGLMPVVsLayer2nd, -10000, -10000, textSizeRel, Form("%s/LG_LandMPVMip_2nd.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
3832     PlotSimple2D( canvas2DCorr, hspectraLGLSigmaVsLayer2nd, -10000, -10000, textSizeRel, Form("%s/LG_LandSigMip_2nd.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
3833     PlotSimple2D( canvas2DCorr, hspectraLGGSigmaVsLayer2nd, -10000, -10000, textSizeRel, Form("%s/LG_GaussSigMip_2nd.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
3834 
3835     PlotSimple2D( canvas2DCorr, hLGHGCorrVsLayer, -10000, -10000, textSizeRel, Form("%s/LG_HG_Corr.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kTRUE, "colz", true, Form( "#LT a_{LGHG} #GT = %.1f", avLGHGCorr));
3836     PlotSimple2D( canvas2DCorr, hLGHGCorrOffsetVsLayer, -10000, -10000, textSizeRel, Form("%s/LG_HG_CorrOffset.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kTRUE, "colz", true, Form( "#LT b_{LGHG} #GT = %.1f", avLGHGOffCorr));
3837     PlotSimple2D( canvas2DCorr, hHGLGCorrVsLayer, -10000, -10000, textSizeRel, Form("%s/HG_LG_Corr.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kTRUE, "colz", true, Form( "#LT a_{HGLG} #GT = %.1f", avHGLGCorr));
3838     PlotSimple2D( canvas2DCorr, hHGLGCorrOffsetVsLayer, -10000, -10000, textSizeRel, Form("%s/HG_LG_CorrOffset.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kTRUE, "colz", true, Form( "#LT b_{HGLG} #GT = %.1f", avHGLGOffCorr));
3839   }
3840 
3841   // Print calib info
3842   calib.PrintGlobalInfo();  
3843   // setup plotting ranges
3844   Int_t textSizePixel = 30;
3845   Double_t minSpec = -100;
3846   Double_t maxHG = ReturnMipPlotRangeDepVov(calib.GetVov(),true, typeRO)*nSampleHGCROCInt;
3847   Double_t maxLG = ReturnMipPlotRangeDepVov(calib.GetVov(),false, typeRO);
3848   std::cout << "plotting single layers" << std::endl;
3849   Double_t maxTriggPPlot = maxHG*2;
3850   if (typeRO != ReadOut::Type::Caen){
3851     maxTriggPPlot = 150;
3852     minSpec = -20;
3853   }
3854 
3855   //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
3856   // Single layer plotting
3857   //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
3858   MultiCanvas panelPlot(detConf, "MipExt");
3859   bool init1D = panelPlot.Initialize(1);
3860   MultiCanvas panelPlot2D(detConf, "MipExt2D");
3861   bool init2D = panelPlot2D.Initialize(2);
3862     
3863   std::cout << "plotting single layers" << std::endl;
3864   if (ExtPlot > 0){
3865     panelPlot.PlotMipWithFits( hSpectra, hSpectraTrigg, 1, minSpec, maxHG, 1.2, 
3866                                Form("%s/MIP_HG" ,outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, skipPlotLayer);
3867     panelPlot.PlotTriggerPrim( hSpectraTrigg, averageScalePerTile, factorMinTrigg, factorMaxTrigg, 0, maxTriggPPlot, 1.2,
3868                              Form("%s/TriggPrimitive" ,outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, skipPlotLayer);
3869 
3870     if (typeRO == ReadOut::Type::Caen) {
3871       panelPlot.PlotMipWithFits( hSpectra, hSpectraTrigg, 0, minSpec, maxLG, 1.2, 
3872                                  Form("%s/MIP_LG" ,outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, skipPlotLayer);
3873       panelPlot2D.PlotCorrWithFits( hSpectra, 0, -20, 800, 0., 3900,
3874                                     Form("%s/LGHG_Corr",outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, skipPlotLayer);
3875     }
3876   }
3877   if (ExtPlot > 1 && typeRO == ReadOut::Type::Caen){
3878       panelPlot2D.PlotCorrWithFits( hSpectra, 1, minSpec, 4000, 0, 340,
3879                                     Form("%s/HGLG_Corr",outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, skipPlotLayer);
3880   }
3881   std::cout << "done plotting" << std::endl;
3882 
3883   return true;
3884 } // end Analyses::GetScaling()
3885 
3886 //***********************************************************************************************
3887 //*********************** improved scaling calculation function *********************************
3888 //***********************************************************************************************
3889 bool Analyses::GetImprovedScaling(void){
3890   std::cout<<"GetImprovedScaling"<<std::endl;
3891   
3892   // read full run list
3893   std::map<int,RunInfo> ri=readRunInfosFromFile(RunListInputName.Data(),debug,0);
3894   
3895   // create tileSpectra objects
3896   std::map<int,TileSpectra> hSpectra;
3897   std::map<int,TileSpectra> hSpectraTrigg;
3898   std::map<int, TileSpectra>::iterator ithSpectra;
3899   std::map<int, TileSpectra>::iterator ithSpectraTrigg;
3900   
3901   // create output file for histos
3902   if (!CreateOutputRootHistFile()) return false;
3903    
3904   // setup general fitting options 
3905   ROOT::Math::MinimizerOptions::SetDefaultMinimizer("Minuit2", "Migrad");
3906   
3907   // reading first event in tree to extract runnumber & RO-type
3908   TdataIn->GetEntry(0);
3909   int evts=TdataIn->GetEntries();
3910   Int_t runNr           = event.GetRunNumber();
3911   ReadOut::Type typeRO  = event.GetROtype();
3912   
3913   // reading calib from file
3914   TcalibIn->GetEntry(0);
3915   //==================================================================================
3916   // extract spectra per tile from event tree
3917   //==================================================================================
3918   // check whether calib should be overwritten based on external text file
3919   if (OverWriteCalib){
3920     calib.ReadCalibFromTextFile(ExternalCalibFile,debug);
3921   }
3922   // read run numbers from calib tree
3923   std::cout<< "original run numbers calib: "<<calib.GetRunNumber() << "\t" << calib.GetRunNumberPed() << "\t" << calib.GetRunNumberMip() << std::endl;
3924   // Get run info object
3925   std::map<int,RunInfo>::iterator it=ri.find(runNr);
3926   // set year of data taking in case adjustments are necessary
3927   SetYear(it->second.year);
3928   
3929   // setup trigger sel
3930   double factorMinTrigg   = 0.8;
3931   double factorMaxTrigg   = 2.5;
3932   
3933   if (  typeRO == ReadOut::Type::Caen ){
3934     if (yearData == 2023){
3935       factorMinTrigg    = 0.9;
3936       factorMaxTrigg    = 2.;
3937     } 
3938   } else if (  typeRO == ReadOut::Type::Hgcroc ){
3939     if (yearData == 2024){
3940       factorMinTrigg    = 0.5;
3941     } else if (yearData == 2025){
3942       factorMinTrigg    = 0.5;
3943     } else if (yearData == 2026){
3944       factorMinTrigg    = 0.8;
3945       if (nSampleHGCROCInt == 3)
3946         factorMinTrigg    = 0.4;
3947       else if (nSampleHGCROCInt == 5)
3948         factorMinTrigg    = 0.4;
3949     }
3950   }
3951   std::cout << "trigger limits set to: " << factorMinTrigg <<"\t" << factorMaxTrigg << std::endl;
3952 
3953   
3954   RootOutputHist->mkdir("IndividualCells");
3955   RootOutputHist->mkdir("IndividualCellsTrigg");
3956   RootOutputHist->cd("IndividualCellsTrigg");  
3957 
3958   // find detector config for plotting
3959   DetConf::Type detConf   = setup->GetDetectorConfig();
3960   
3961   
3962   int evtDeb = 5000;
3963   if (typeRO != ReadOut::Type::Caen){
3964     evtDeb = 2500;    
3965   }
3966   
3967   if (maxEvents == -1){
3968     maxEvents = evts;
3969   } else {
3970     std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
3971     std::cout << "ATTENTION: YOU ARE RESETTING THE MAXIMUM NUMBER OF EVENTS TO BE PROCESSED TO: " << maxEvents << ". THIS SHOULD ONLY BE USED FOR TESTING!" << std::endl;
3972     std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
3973   }
3974 
3975   //=============================================================================================
3976   // Setup general variables for analysis
3977   //=============================================================================================
3978   int actCh1st                = 0;
3979   double averageScale         = calib.GetAverageScaleHigh(actCh1st);
3980   int actChalt                = 0;
3981   double averageNTiles        = 0.;
3982   double averageScalePerTile  = calib.GetAverageScaleHighPerSingleLayer(actChalt, averageNTiles);
3983   // variable per single tile for possible summed output
3984   double avLGHGCorr           = calib.GetAverageLGHGCorr();
3985   double avLGHGCorrOff        = calib.GetAverageLGHGCorrOff();
3986   
3987   int actCh1stL                = 0;
3988   double averageScaleL        = 0;
3989   int actChaltL               = 0;
3990   double averageNTilesL       = 0.;
3991   double averageLScalePerTile = 0.;
3992   if (typeRO == ReadOut::Type::Caen){
3993     averageScaleL        = calib.GetAverageScaleLow(actCh1stL);
3994     averageLScalePerTile = calib.GetAverageScaleLowPerSingleLayer(actChaltL, averageNTilesL);
3995   }
3996   // print out key calib variables
3997   if (typeRO == ReadOut::Type::Caen){
3998     std::cout << "average HG mip: " << averageScale << "\t per tile: " << averageScalePerTile<< "\t active ch: "<< actCh1st<< std::endl;
3999     std::cout << "average LG mip: " << averageScaleL <<"\t per tile: " << averageLScalePerTile<< "\t active ch: "<< actCh1stL<< std::endl;
4000   } else if (typeRO == ReadOut::Type::Hgcroc){
4001     std::cout << "average HG mip: " << averageScale << "\t per tile: " << averageScalePerTile << "\t active ch: "<< actCh1st<< "\t average Ntiles for calib: "<< averageNTiles << std::endl;
4002   }
4003   
4004   // Set correct calib scale for trigger eval
4005   double calibScale           = 0;
4006   if (typeRO == ReadOut::Type::Caen ){
4007     // LG scale as evaluated from fits
4008     if (calibOption == 0){
4009       calibScale  = averageLScalePerTile;
4010       std::cout << "Estimating triggers using calib option " << calibOption << ". This uses the average of all LG evaluated fits, averages is: " << calibScale << std::endl;
4011     // LG scale calc from HG
4012     } else if (calibOption == 1){
4013       calibScale  = (averageScalePerTile-avLGHGCorrOff)/avLGHGCorr;
4014       std::cout << "Estimating triggers using calib option " << calibOption << ". This uses the average of all HG evaluated fits and calculates LG equivalent, averages is: " << calibScale << std::endl;
4015     // HG scale as evaluated from fits
4016     } else if (calibOption >= 2){
4017       calibScale  = averageScalePerTile;
4018       std::cout << "Estimating triggers using calib option " << calibOption << ". This uses the average of all HG evaluated fits, averages is: " << calibScale << std::endl;
4019     } else {
4020       std::cout << "This calib option is unknown: " << calibOption << " *************** ABORTING!!!!" << std::endl;
4021       return false;
4022     }
4023   } else {
4024     calibScale  = averageScalePerTile;
4025     std::cout << " Calibrating using average ADC max fits, averages is: " << calibScale << std::endl;
4026   }
4027 
4028   //==================================================================================
4029   // process events from tree for mip fitting
4030   //==================================================================================
4031   for(int i=0; i<maxEvents; i++){
4032     TdataIn->GetEntry(i);
4033     if (i%evtDeb == 0 && i > 0 && debug > 0) std::cout << "Reading " <<  i << " / " << maxEvents << " events" << std::endl;
4034     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4035     // process tiles in event
4036     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++    
4037     for(int j=0; j<event.GetNTiles(); j++){
4038       //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4039       // CAEN treatment
4040       //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4041       if (typeRO == ReadOut::Type::Caen) {
4042         Caen* aTile=(Caen*)event.GetTile(j);
4043         if (i == 0 && debug > 2) std::cout << ((TString)setup->DecodeCellID(aTile->GetCellID())).Data() << std::endl;
4044         long currCellID = aTile->GetCellID();
4045         
4046         // read current tile
4047         ithSpectraTrigg=hSpectraTrigg.find(currCellID);
4048         double hgCorr = aTile->GetADCHigh()-calib.GetPedestalMeanH(currCellID);
4049         double lgCorr = aTile->GetADCLow()-calib.GetPedestalMeanL(currCellID);
4050 
4051         // estimate local muon trigger
4052         bool localMuonTrigg = event.InspectIfLocalMuonTrigg(currCellID, calibScale, factorMinTrigg, factorMaxTrigg);
4053         
4054         if(ithSpectraTrigg!=hSpectraTrigg.end()){
4055           ithSpectraTrigg->second.FillTrigger(aTile->GetLocalTriggerPrimitive());
4056         } else {
4057           RootOutputHist->cd("IndividualCellsTrigg");
4058           hSpectraTrigg[currCellID]=TileSpectra("mipTrigg",currCellID,calib.GetTileCalib(currCellID),event.GetROtype(),nSampleHGCROCInt,debug);
4059           hSpectraTrigg[currCellID].FillTrigger(aTile->GetLocalTriggerPrimitive());;
4060           RootOutput->cd();
4061         }
4062         
4063         ithSpectra=hSpectra.find(currCellID);
4064         if (ithSpectra!=hSpectra.end()){
4065           ithSpectra->second.FillSpectraCAEN(lgCorr,hgCorr);
4066           if (hgCorr > 3*calib.GetPedestalSigH(currCellID) && lgCorr > 3*calib.GetPedestalSigL(currCellID) && hgCorr < 3900 )
4067             ithSpectra->second.FillCorrCAEN(lgCorr,hgCorr);
4068         } else {
4069           RootOutputHist->cd("IndividualCells");
4070           hSpectra[currCellID]=TileSpectra("mip1st",currCellID,calib.GetTileCalib(currCellID),event.GetROtype(),nSampleHGCROCInt, debug);
4071           hSpectra[currCellID].FillSpectraCAEN(lgCorr,hgCorr);;
4072           if (hgCorr > 3*calib.GetPedestalSigH(currCellID) && lgCorr > 3*calib.GetPedestalSigL(currCellID && hgCorr < 3900) )
4073             hSpectra[currCellID].FillCorrCAEN(lgCorr,hgCorr);;
4074 
4075           RootOutput->cd();
4076         }
4077         
4078         // only fill tile spectra if 4 surrounding tiles on average are compatible with muon response
4079         if (localMuonTrigg){
4080           aTile->SetLocalTriggerBit(1);
4081           ithSpectraTrigg=hSpectraTrigg.find(aTile->GetCellID());
4082           ithSpectraTrigg->second.FillSpectraCAEN(lgCorr,hgCorr);
4083           if (hgCorr > 3*calib.GetPedestalSigH(currCellID) && lgCorr > 3*calib.GetPedestalSigL(currCellID) && hgCorr < 3900 )
4084             ithSpectraTrigg->second.FillCorrCAEN(lgCorr,hgCorr);
4085         }
4086       //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
4087       // HGCROC treatment
4088       //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4089       } else if (typeRO == ReadOut::Type::Hgcroc) {
4090         Hgcroc* aTile=(Hgcroc*)event.GetTile(j);
4091         if (i == 0 && debug > 2) std::cout << ((TString)setup->DecodeCellID(aTile->GetCellID())).Data() << std::endl;
4092         long currCellID = aTile->GetCellID();
4093 
4094         ithSpectraTrigg=hSpectraTrigg.find(currCellID);
4095         // double adc = aTile->GetPedestal()+aTile->GetIntegratedADC();
4096         double adc = aTile->GetIntegratedADC();
4097         double tot = aTile->GetRawTOT();
4098         double toa = aTile->GetRawTOA();
4099         
4100         // estimate local muon trigger
4101         bool localMuonTrigg = event.InspectIfLocalMuonTrigg(currCellID, calibScale, factorMinTrigg, factorMaxTrigg);
4102         
4103         if(ithSpectraTrigg!=hSpectraTrigg.end()){
4104           ithSpectraTrigg->second.FillTrigger(aTile->GetLocalTriggerPrimitive());
4105         } else {
4106           RootOutputHist->cd("IndividualCellsTrigg");
4107           hSpectraTrigg[currCellID]=TileSpectra("mipTrigg",currCellID,calib.GetTileCalib(currCellID),event.GetROtype(), nSampleHGCROCInt,debug);
4108           hSpectraTrigg[currCellID].FillTrigger(aTile->GetLocalTriggerPrimitive());;
4109           RootOutput->cd();
4110         }
4111 
4112         ithSpectra=hSpectra.find(currCellID);
4113         if (ithSpectra!=hSpectra.end()){
4114           ithSpectra->second.FillHGCROC(adc, toa, tot);
4115         } else {
4116           RootOutputHist->cd("IndividualCells");
4117           hSpectra[currCellID]=TileSpectra("mip1st",currCellID,calib.GetTileCalib(currCellID),event.GetROtype(), nSampleHGCROCInt, debug);
4118           hSpectra[currCellID].FillHGCROC(adc, toa, tot);
4119           RootOutput->cd();
4120         }
4121         
4122         // only fill tile spectra if 4 surrounding tiles on average are compatible with muon response
4123         if (localMuonTrigg){
4124           aTile->SetLocalTriggerBit(1);
4125           ithSpectraTrigg=hSpectraTrigg.find(currCellID);
4126           ithSpectraTrigg->second.FillHGCROC(adc, toa, tot);
4127         }
4128       }
4129     }
4130     RootOutput->cd();
4131     // fill tree
4132     if(!NoEventTreeWrite) TdataOut->Fill();
4133   }
4134   // write tree
4135   if(!NoEventTreeWrite) TdataOut->Write();
4136   TsetupIn->CloneTree()->Write();
4137   
4138   //==================================================================================
4139   // Monitoring histos for fits results 
4140   //==================================================================================
4141   RootOutputHist->cd();
4142   int maxChannelPerLayer             = (setup->GetNMaxColumn()+1)*(setup->GetNMaxRow()+1)*(setup->GetNMaxModule()+1);
4143   int maxChannelPerLayerSingleMod    = (setup->GetNMaxColumn()+1)*(setup->GetNMaxRow()+1);
4144 
4145   // monitoring trigger 
4146   TH2D* hmipTriggers              = new TH2D( "hmipTriggers","muon triggers; layer; brd channel; counts ",
4147                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
4148   hmipTriggers->SetDirectory(0);
4149   TH2D* hSuppresionNoise          = new TH2D( "hSuppresionNoise","S/B noise region; layer; brd channel; S/B noise region",
4150                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
4151   hSuppresionNoise->SetDirectory(0);
4152   TH2D* hSuppresionSignal         = new TH2D( "hSuppresionSignal","S/B signal region; layer; brd channel; S/B signal region",
4153                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
4154   hSuppresionSignal->SetDirectory(0);
4155 
4156   // monitoring 2nd iteration mip fits
4157   TH2D* hspectraHGMaxVsLayer   = new TH2D( "hspectraHGMaxVsLayer","Max High Gain; layer; brd channel; Max_{HG, 2^{nd}} (arb. units) ",
4158                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
4159   hspectraHGMaxVsLayer->SetDirectory(0);
4160   TH2D* hspectraHGFWHMVsLayer   = new TH2D( "hspectraHGFWHMVsLayer","FWHM High Gain; layer; brd channel; FWHM_{HG, 2^{nd}} (arb. units) ",
4161                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
4162   hspectraHGFWHMVsLayer->SetDirectory(0);
4163   TH2D* hspectraHGLMPVVsLayer   = new TH2D( "hspectraHGLMPVVsLayer","MPV High Gain; layer; brd channel; MPV_{HG, 2^{nd}} (arb. units) ",
4164                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
4165   hspectraHGLMPVVsLayer->SetDirectory(0);
4166   TH2D* hspectraHGLSigmaVsLayer = new TH2D( "hspectraHGLSigmaVsLayer","Sigma Landau High Gain; layer; brd channel; #sigma_{L,HG, 2^{nd}} (arb. units) ",
4167                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
4168   hspectraHGLSigmaVsLayer->SetDirectory(0);
4169   TH2D* hspectraHGGSigmaVsLayer = new TH2D( "hspectraHGGSigmaVsLayer","Sigma Gauss High Gain; layer; brd channel; #sigma_{G,HG, 2^{nd}} (arb. units) ",
4170                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
4171   hspectraHGGSigmaVsLayer->SetDirectory(0);
4172   TH2D* hspectraLGMaxVsLayer   = new TH2D( "hspectraLGMaxVsLayer","Max High Gain; layer; brd channel; Max_{LG, 2^{nd}} (arb. units) ",
4173                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
4174   hspectraLGMaxVsLayer->SetDirectory(0);
4175   TH2D* hspectraLGFWHMVsLayer   = new TH2D( "hspectraLGFWHMVsLayer","FWHM High Gain; layer; brd channel; FWHM_{LG, 2^{nd}} (arb. units) ",
4176                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
4177   hspectraLGFWHMVsLayer->SetDirectory(0);
4178   TH2D* hspectraLGLMPVVsLayer   = new TH2D( "hspectraLGLMPVVsLayer","MPV High Gain; layer; brd channel; MPV_{LG, 2^{nd}} (arb. units) ",
4179                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
4180   hspectraLGLMPVVsLayer->SetDirectory(0);
4181   TH2D* hspectraLGLSigmaVsLayer = new TH2D( "hspectraLGLSigmaVsLayer","Sigma Landau High Gain; layer; brd channel; #sigma_{L,LG, 2^{nd}} (arb. units) ",
4182                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
4183   hspectraLGLSigmaVsLayer->SetDirectory(0);
4184   TH2D* hspectraLGGSigmaVsLayer = new TH2D( "hspectraLGGSigmaVsLayer","Sigma Gauss High Gain; layer; brd channel; #sigma_{G,LG, 2^{nd}} (arb. units) ",
4185                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
4186   hspectraLGGSigmaVsLayer->SetDirectory(0);
4187 
4188   TH1D* hRatioMaxLGCalcLG             = new TH1D( "hRatioMaxLGCalcLG","Max_{LG Calc}/Max_{LG} ;Max_{LG Calc}/Max_{LG} ; counts ",
4189                                             200, 0, 2);
4190   hRatioMaxLGCalcLG->SetDirectory(0);
4191   TH1D* hRatioMaxLGCalcAlterLG             = new TH1D( "hRatioMaxLGCalcAlterLG","Max_{LG Calc alter}/Max_{LG} ;Max_{LG Calc}/Max_{LG} ; counts ",
4192                                             200, 0, 2);
4193   hRatioMaxLGCalcAlterLG->SetDirectory(0);
4194   TH1D* hRatioMaxLGHG             = new TH1D( "hRatioMaxLGHG","Max Low Gain/ Max High Gain ;Max_{LG}/ Max_{HG} ; counts ",
4195                                             400, 0, 1);
4196   hRatioMaxLGHG->SetDirectory(0);
4197 
4198   
4199   TH2D* hHGscaleChi2VsLayer = new TH2D( "hHGscaleChi2VsLayer", "HG MIP fit #chi^{2}/NDF; layer; brd channel; #chi^{2}/ndf ", 
4200                                     setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5); // -EP
4201   hHGscaleChi2VsLayer->SetDirectory(0); 
4202 
4203   TH2D* hSNRTriggVsLayer = new TH2D( "hSNRTriggVsLayer", "HG Triggered S/N; layers; brd channel; SNR ", 
4204                                     setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5); // -EP
4205   hSNRTriggVsLayer->SetDirectory(0);
4206 
4207   //TH2D* hChi2VsNMipTrigg = new TH2D( "hChi2VsNMipTrigg", "HG MiP fit by stats; Number of MIP triggers; #chi^{2}/ndf; ", 50, 0, 10000, 80, 0, 20); // -EP
4208   //hChi2VsNMipTrigg->SetDirectory(0);
4209 
4210   //TH1D *hSNRTrigg = new TH1D("hSNRTrigg", "Signal to Noise Ratio; SNR; counts", 100, 0, 50); // -EP
4211   //hSNRTrigg->SetDirectory(0);
4212 
4213   // 2D beam profile -EP 
4214   int absMaxCols = setup->GetAbsMaxColumnsSetup(detConf);
4215   int absMaxRows = setup->GetAbsMaxRowsSetup(detConf);
4216   std::cout << "Outer dimensions: " << std::endl;
4217   std::cout << "\t x: " << setup->GetMinX() << " - " << setup->GetMaxX() << "\t" << setup->GetAbsMaxColumnsSetup(detConf)<< std::endl;
4218   std::cout << "\t y: " << setup->GetMinY() << " - " << setup->GetMaxY() << "\t" << setup->GetAbsMaxRowsSetup(detConf)<< std::endl;
4219   std::cout << "\t z: " << setup->GetMinZ() << " - " << setup->GetMaxZ() << "\t" << setup->GetNMaxLayer()+1<< std::endl;
4220   
4221   TH2D* hMipTriggXY = new TH2D( "hMipTriggXY", "MIP Triggers summed over layers; X (col); Y (row); Num triggers", absMaxCols, -0.5, absMaxCols-0.5, absMaxRows, -0.5, absMaxRows-0.5);
4222   hMipTriggXY->SetDirectory(0);
4223 
4224   // 3D beam profile -EP
4225   int absMaxLayers = (int)setup->GetNMaxLayer()+1;
4226   TH3D *hMipTriggXYZ = new TH3D( "hMipTriggXYZ", "MIP Triggers; X (col); Z (layer); Y (row); Num triggers", absMaxCols, -0.5, absMaxCols-0.5, absMaxLayers, -0.5, absMaxLayers-0.5, absMaxRows, -0.5, absMaxRows-0.5);
4227   hMipTriggXYZ->SetDirectory(0);
4228 
4229   TH2D* hMPVvsNoisePeak = new TH2D( "hMPVvsNoisePeak", "Signal to noise peak ADC; noise peak (ADC); MIP MPV (ADC); ", 20, -5, 10, 20, 0, 50); // -EP
4230   hMPVvsNoisePeak->SetDirectory(0);
4231 
4232   //TH1D* hPeakSeparation = new TH1D("hPeakSeparation", "Signal-noise peak separation; MPV - noise peak (ADC); counts", 35, 0, 35); // -EP
4233   ///hPeakSeparation->SetDirectory(0);
4234 
4235   //==================================================================================
4236   // mip fitting spectra for each cell
4237   //==================================================================================
4238   int currCells = 0;
4239   double* parameters    = new double[6];
4240   double* parErrAndRes  = new double[6];
4241   bool isGood;
4242   double meanSB_NoiseR  = 0;
4243   double meanSB_SigR    = 0;
4244   if ( debug > 0){
4245     std::cout << "============================== start fitting improved iteration" << std::endl;  
4246   }
4247 
4248   int optHGCROC = 0;
4249   if (typeRO == ReadOut::Type::Hgcroc){
4250     optHGCROC = 1;
4251   }
4252   // define CalibSummary object for this run -EP
4253   CalibSummary tileSum = CalibSummary(calib.GetRunNumber(), calib.GetRunNumber(), calib.GetVop(), it->second.pdg, optHGCROC);
4254   tileSum.SetRunProperties(it->second);
4255   tileSum.SetRefRunNr(calib.GetRunNumber());
4256 
4257   for(ithSpectraTrigg=hSpectraTrigg.begin(); ithSpectraTrigg!=hSpectraTrigg.end(); ++ithSpectraTrigg){ // GetImprovedScaling() spectra loop
4258     if (currCells%20 == 0 && currCells > 0 && debug > 0)
4259       std::cout << "============================== cell " <<  currCells << " / " << hSpectraTrigg.size() << " cells" << std::endl;
4260     currCells++;
4261     long cellID     = ithSpectraTrigg->second.GetCellID();    
4262     ithSpectra      = hSpectra.find(cellID);
4263     if (calib.GetBadChannel(cellID) < 2){
4264       if ( debug > 1)std::cout << "=======> skipped cell " << cellID << " masked in BC map" << std::endl;
4265       continue;
4266     }
4267     // HGCROC data has unphysical bin-to-bin jumps add XX% sys on top of individual for fitting
4268     double relSysF  = 0.15;
4269     if (typeRO == ReadOut::Type::Hgcroc){
4270       // ithSpectra->second.GetHG()->Rebin(2);
4271       // ithSpectraTrigg->second.GetHG()->Rebin(2);
4272       for (Int_t b = 1; b < ithSpectraTrigg->second.GetHG()->GetNbinsX()+1; b++){
4273         double errWithSys= TMath::Sqrt(relSysF*relSysF+TMath::Power(ithSpectra->second.GetHG()->GetBinError(b)/ithSpectra->second.GetHG()->GetBinContent(b),2))*ithSpectra->second.GetHG()->GetBinContent(b);
4274         double errWithSysT= TMath::Sqrt(relSysF*relSysF+TMath::Power(ithSpectraTrigg->second.GetHG()->GetBinError(b)/ithSpectraTrigg->second.GetHG()->GetBinContent(b),2))*ithSpectraTrigg->second.GetHG()->GetBinContent(b);
4275         ithSpectra->second.GetHG()->SetBinError(b,errWithSys);        
4276         ithSpectraTrigg->second.GetHG()->SetBinError(b,errWithSysT);
4277       }
4278     }
4279 
4280     for (int p = 0; p < 6; p++){
4281       parameters[p]   = 0;
4282       parErrAndRes[p] = 0;
4283     }
4284     
4285     isGood=ithSpectraTrigg->second.FitMipHG(parameters, parErrAndRes, debug, yearData, true, calib.GetVov(), averageScale);
4286   
4287     tileSum.Fill(ithSpectraTrigg->second.GetCalib());
4288     
4289     // get reduced chi^2 from mip peak fit
4290     double redChi2 = parErrAndRes[4] / parErrAndRes[5]; // chi2/ndf
4291 
4292     int layer       = setup->GetLayer(cellID);
4293     int chInLayer   = setup->GetChannelInLayerFull(cellID, detConf);
4294     int row         = setup->GetRow(cellID);
4295     int col         = setup->GetColumn(cellID);
4296     int mod         = setup->GetModule(cellID);
4297     int bin2D       = hspectraHGMaxVsLayer->FindBin(layer,chInLayer);
4298   
4299     double pedSigHG = calib.GetPedestalSigH(cellID);
4300     double maxBin   = 0;
4301     if (typeRO == ReadOut::Type::Caen){ 
4302       maxBin   = 3800;
4303     } else {
4304       maxBin   = 1024;
4305     }
4306 
4307     Int_t binNLow   = ithSpectraTrigg->second.GetHG()->FindBin(-1*pedSigHG);
4308     Int_t binNHigh  = ithSpectraTrigg->second.GetHG()->FindBin(3*pedSigHG);
4309     Int_t binSHigh  = ithSpectraTrigg->second.GetHG()->FindBin(maxBin);
4310     
4311         // S ~ mip triggers, B ~ everything
4312     double S_NoiseR = ithSpectraTrigg->second.GetHG()->Integral(binNLow, binNHigh);
4313     double S_SigR   = ithSpectraTrigg->second.GetHG()->Integral(binNHigh, binSHigh);
4314     
4315     double B_NoiseR = ithSpectra->second.GetHG()->Integral(binNLow , binNHigh);
4316     double B_SigR   = ithSpectra->second.GetHG()->Integral(binNHigh, binSHigh);
4317     
4318     double SB_NoiseR  = (B_NoiseR != 0.) ? S_NoiseR/B_NoiseR : 0; // triggered noise / full noise (suppression of noise region from applying mip trigger) 
4319     double SB_SigR    = (B_SigR != 0.) ? S_SigR/B_SigR : 0; // suppression of signal region from applying mip trigger
4320     
4321     meanSB_NoiseR += SB_NoiseR;
4322     meanSB_SigR += SB_SigR;
4323 
4324     double SNR_trigg = (S_NoiseR != 0.) ? S_SigR/S_NoiseR : 0;
4325 
4326     hmipTriggers->SetBinContent(bin2D, ithSpectraTrigg->second.GetHG()->GetEntries());
4327     hSuppresionNoise->SetBinContent(bin2D, SB_NoiseR);
4328     hSuppresionSignal->SetBinContent(bin2D, SB_SigR);
4329     hSNRTriggVsLayer->SetBinContent(bin2D, SNR_trigg);
4330   
4331     // get 2D and 3D beam profiles 
4332     int thisbinx = setup->GetAbsColumn(cellID, detConf)+1; // the +1s are due to the 0th bin in root being underflow
4333     int thisbiny = setup->GetAbsRow(cellID, detConf) +1;
4334     int thisbinz = layer + 1;
4335     int numMipTrig = ithSpectraTrigg->second.GetHG()->GetEntries();
4336     hMipTriggXY->SetBinContent(thisbinx, thisbiny, hMipTriggXY->GetBinContent(thisbinx, thisbiny) + numMipTrig);
4337     hMipTriggXYZ->SetBinContent(thisbinx, thisbinz, thisbiny, numMipTrig);
4338   
4339     
4340     
4341     // estimate separation between noise and mip peaks
4342     //double peaksep = parameters[1]-ithSpectraTrigg->second.GetMaxXInRangeHG(-1*pedSigHG, 3*pedSigHG);
4343 
4344     double maxHG      = -10000.;
4345     double maxLG      = -10000.;
4346     double maxLGCalc  = -10000.;
4347     double maxLGCalcA = -10000.;
4348     if (isGood){
4349       hMPVvsNoisePeak->Fill(ithSpectraTrigg->second.GetMaxXInRangeHG(-1*pedSigHG, 3*pedSigHG), parameters[1]);
4350       //hPeakSeparation->Fill(peaksep);
4351       //hSNRTrigg->Fill(SNR_trigg);
4352       hHGscaleChi2VsLayer->SetBinContent(bin2D, redChi2);
4353       //hChi2VsNMipTrigg->Fill(numMipTrig, redChi2);     
4354       
4355       // get uncertainty on HG Max
4356       double rel_err_L_MPV = parErrAndRes[1]/parameters[1]; // Landau MPV error / MPV
4357       double sigma_Max = rel_err_L_MPV * parameters[4]; // relative MPV err * Max ADC value
4358       hspectraHGMaxVsLayer->SetBinContent(bin2D, parameters[4]);
4359       hspectraHGMaxVsLayer->SetBinError(bin2D, sigma_Max);
4360       hspectraHGFWHMVsLayer->SetBinContent(bin2D, parameters[5]);
4361       hspectraHGLMPVVsLayer->SetBinContent(bin2D, parameters[1]);
4362       hspectraHGLMPVVsLayer->SetBinError(bin2D, parErrAndRes[1]);
4363       hspectraHGLSigmaVsLayer->SetBinContent(bin2D, parameters[0]);
4364       hspectraHGLSigmaVsLayer->SetBinError(bin2D, parErrAndRes[0]);
4365       hspectraHGGSigmaVsLayer->SetBinContent(bin2D, parameters[3]);
4366       hspectraHGGSigmaVsLayer->SetBinError(bin2D, parErrAndRes[3]);
4367       maxHG       = parameters[4];
4368       maxLGCalc   = calib.GetCalcScaleLow(cellID);
4369       maxLGCalcA  = calib.GetCalcScaleLowAlter(cellID);
4370     }
4371     
4372     if (typeRO == ReadOut::Type::Caen) {
4373       for (int p = 0; p < 6; p++){
4374         parameters[p]   = 0;
4375         parErrAndRes[p] = 0;
4376       }
4377       isGood=ithSpectraTrigg->second.FitMipLG(parameters, parErrAndRes, debug, yearData, true, calib.GetVov(),  averageScaleL);
4378       if (isGood){  
4379         hspectraLGMaxVsLayer->SetBinContent(bin2D, parameters[4]);
4380         hspectraLGFWHMVsLayer->SetBinContent(bin2D, parameters[5]);
4381         hspectraLGLMPVVsLayer->SetBinContent(bin2D, parameters[1]);
4382         hspectraLGLMPVVsLayer->SetBinError(bin2D, parErrAndRes[1]);
4383         hspectraLGLSigmaVsLayer->SetBinContent(bin2D, parameters[0]);
4384         hspectraLGLSigmaVsLayer->SetBinError(bin2D, parErrAndRes[0]);
4385         hspectraLGGSigmaVsLayer->SetBinContent(bin2D, parameters[3]);
4386         hspectraLGGSigmaVsLayer->SetBinError(bin2D, parErrAndRes[3]);
4387         maxLG = parameters[4];
4388         hRatioMaxLGCalcLG->Fill(maxLGCalc/maxLG);
4389         hRatioMaxLGCalcAlterLG->Fill(maxLGCalcA/maxLG);
4390         hRatioMaxLGHG->Fill(maxLG/maxHG);
4391       }
4392     }
4393     
4394     
4395   } // end GetImprovedScaling() spectra loop
4396   if ( debug > 0)
4397     std::cout << "============================== done fitting improved iteration" << std::endl;
4398 
4399   
4400   meanSB_NoiseR = meanSB_NoiseR/hSpectraTrigg.size();
4401   meanSB_SigR   = meanSB_SigR/hSpectraTrigg.size();
4402   //==================================================================================
4403   // write calibration to file
4404   //==================================================================================
4405   RootOutput->cd();
4406   
4407   if (IsCalibSaveToFile()){
4408     TString fileCalibPrint = RootOutputName;
4409     fileCalibPrint         = fileCalibPrint.ReplaceAll(".root","_calib.txt");
4410     calib.PrintCalibToFile(fileCalibPrint);
4411   }
4412   
4413   TcalibOut->Fill();
4414   TcalibOut->Write();
4415   int actChA                     = 0;
4416   double averageScaleUpdated     = calib.GetAverageScaleHigh(actChA);
4417   double averageScaleUpdatedLow  = 0.;
4418   int actChAalt                  = 0;
4419   double averageNTilesA          = 0.;
4420   double averageScaleUpPerTile   = calib.GetAverageScaleHighPerSingleLayer(actChAalt, averageNTilesA);
4421   double meanFWHMHG              = calib.GetAverageScaleWidthHigh();
4422   double meanFWHMLG              = 0.;
4423 
4424   if (typeRO == ReadOut::Type::Caen) {
4425     averageScaleUpdatedLow  = calib.GetAverageScaleLow();
4426     meanFWHMLG              = calib.GetAverageScaleWidthLow();
4427   }
4428   
4429   if (typeRO == ReadOut::Type::Caen) {
4430     std::cout << "average input HG mip: " << averageScale << " LG mip: "<< averageScaleL << "\t act. ch: "<< actCh1st<< std::endl;
4431     std::cout << "average updated HG mip: " << averageScaleUpdated << " LG mip: "<< averageScaleUpdatedLow << "\t act. ch: "<< actChA<< std::endl;
4432   } else {
4433     std::cout << "average input mip: " << averageScale << " per tile mip: "<< averageScalePerTile << "\t act. ch: "<< actCh1st << "\t av tiles/seg "<< averageNTiles << std::endl;
4434     std::cout << "average updated mip: " << averageScaleUpdated << " per tile mip: "<< averageScaleUpPerTile << "\t act. ch: "<< actChA<< "\t av tiles/seg "<< averageNTilesA << std::endl;
4435   }
4436   RootOutput->Close();
4437   
4438   //==================================================================================
4439   // write hists to histo output file
4440   //==================================================================================
4441   RootOutputHist->cd("IndividualCellsTrigg");
4442     for(ithSpectra=hSpectraTrigg.begin(); ithSpectra!=hSpectraTrigg.end(); ++ithSpectra){
4443       ithSpectra->second.Write(true);
4444     }
4445   RootOutputHist->cd();
4446     
4447     hspectraHGMaxVsLayer->Write();
4448     hspectraHGFWHMVsLayer->Write();
4449     hspectraHGLMPVVsLayer->Write();
4450     hspectraHGLSigmaVsLayer->Write();
4451     hspectraHGGSigmaVsLayer->Write();
4452     hHGscaleChi2VsLayer->Write();
4453     //hChi2VsNMipTrigg->Write();
4454     hMPVvsNoisePeak->Write();
4455     hSNRTriggVsLayer->Write();
4456     //hPeakSeparation->Write();
4457     //hSNRTrigg->Write();
4458     hMipTriggXY->Write();
4459     hMipTriggXYZ->Write();
4460     if (typeRO == ReadOut::Type::Caen){
4461       hspectraLGMaxVsLayer->Write();
4462       hspectraLGFWHMVsLayer->Write();
4463       hspectraLGLMPVVsLayer->Write();
4464       hspectraLGLSigmaVsLayer->Write();
4465       hspectraLGGSigmaVsLayer->Write();
4466       hRatioMaxLGCalcLG->Write();
4467       hRatioMaxLGCalcAlterLG->Write();
4468       hRatioMaxLGHG->Write();
4469     }
4470     hmipTriggers->Write();
4471     hSuppresionNoise->Write();
4472     hSuppresionSignal->Write();
4473     
4474     tileSum.Write(RootOutputHist);
4475   // fill calib tree & write it
4476   // close open root files
4477   RootOutputHist->Write();
4478   RootOutputHist->Close();
4479 
4480   // close open input root file
4481   RootInput->Close();
4482 
4483   //==================================================================================
4484   // Set up general plotting variables
4485   //==================================================================================  
4486   // create directory for plot output
4487   TString outputDirPlots  = GetPlotOutputDir();
4488   gSystem->Exec("mkdir -p "+outputDirPlots);
4489   
4490   Double_t textSizeRel = 0.035;
4491   StyleSettingsBasics("pdf");
4492   SetPlotStyle();  
4493   std::map<int, CalibSummary> sumCalibs;
4494   sumCalibs[runNr]=tileSum;
4495 
4496   //==================================================================================
4497   // Create canvases for channel overview plotting
4498   //==================================================================================
4499   TCanvas* canvas2DCorr = new TCanvas("canvasCorrPlots","",0,0,1450,1300);  // gives the page size
4500   DefaultCanvasSettings( canvas2DCorr, 0.08, 0.13, 0.045, 0.07);
4501   TCanvas* canvas1DRunsOverlay = new TCanvas("canvas1DRunsOverlay","",0,0,1450,1300);  // gives the page size
4502   DefaultCanvasSettings( canvas1DRunsOverlay, 0.075, 0.015, 0.025, 0.09);
4503 
4504   canvas2DCorr->SetLogz(0);
4505   PlotSimple2D( canvas2DCorr, hspectraHGMaxVsLayer, -10000, -10000, textSizeRel, Form("%s/HG_MaxMip.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true, Form( "#LT Max_{HG} #GT = %.1f", averageScaleUpdated) );
4506   PlotSimple2D( canvas2DCorr, hspectraHGFWHMVsLayer, -10000, -10000, textSizeRel, Form("%s/HG_FWHMMip.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true, Form( "#LT FWHM_{HG} #GT = %.1f", meanFWHMHG));
4507   PlotSimple2D( canvas2DCorr, hspectraHGLMPVVsLayer, -10000, -10000, textSizeRel, Form("%s/HG_LandMPVMip.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
4508   PlotSimple2D( canvas2DCorr, hspectraHGLSigmaVsLayer, -10000, -10000, textSizeRel, Form("%s/HG_LandSigMip.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
4509   PlotSimple2D( canvas2DCorr, hspectraHGGSigmaVsLayer, -10000, -10000, textSizeRel, Form("%s/HG_GaussSigMip.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
4510   PlotSimple2D( canvas2DCorr, hSNRTriggVsLayer, -10000, -10000, textSizeRel, Form("%s/SNRTriggVsLayer.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
4511   PlotSimple2D( canvas2DCorr, hHGscaleChi2VsLayer, -10000, -10000, textSizeRel, Form("%s/HGscaleChi2VsLayer.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
4512   PlotSimple2D( canvas2DCorr, hMipTriggXY, -10000, -10000, textSizeRel, Form("%s/MipTriggXY.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
4513   
4514   canvas2DCorr->SetLogz(1);
4515   TString drawOpt = "colz";
4516   if (yearData == 2023)
4517     drawOpt = "colz,text";
4518   PlotSimple2D( canvas2DCorr, hmipTriggers, -10000, -10000, textSizeRel, Form("%s/MuonTriggers.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, drawOpt, true, Form( "evt. collected = %d", evts));
4519   PlotSimple2D( canvas2DCorr, hSuppresionNoise, -10000, -10000, textSizeRel, Form("%s/SuppressionNoise.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, drawOpt, true, Form( "#LT S/B noise #GT = %.3f", meanSB_NoiseR));
4520   PlotSimple2D( canvas2DCorr, hSuppresionSignal, -10000, -10000, textSizeRel, Form("%s/SuppressionSignal.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, drawOpt, true, Form( "#LT S/B signal #GT = %.3f", meanSB_SigR));
4521 
4522   PlotCalibRunOverlay( canvas1DRunsOverlay, 0, sumCalibs, textSizeRel, 
4523                       Form("%s/HGPedSummary.%s",outputDirPlots.Data(),plotSuffix.Data()), it->second,"", debug);
4524   PlotCalibRunOverlay( canvas1DRunsOverlay, 1, sumCalibs, textSizeRel, 
4525                       Form("%s/HGPedWidthSummary.%s",outputDirPlots.Data(),plotSuffix.Data()), it->second,"", debug);
4526   PlotCalibRunOverlay( canvas1DRunsOverlay, 2, sumCalibs, textSizeRel, 
4527                       Form("%s/LGPedSummary.%s",outputDirPlots.Data(),plotSuffix.Data()), it->second,"", debug);
4528   PlotCalibRunOverlay( canvas1DRunsOverlay, 3, sumCalibs, textSizeRel, 
4529                       Form("%s/LGPedWidthSummary.%s",outputDirPlots.Data(),plotSuffix.Data()), it->second,"", debug);
4530   PlotCalibRunOverlay( canvas1DRunsOverlay, 4, sumCalibs, textSizeRel, 
4531                     Form("%s/HGScaleSummary.%s",outputDirPlots.Data(),plotSuffix.Data()), it->second,"", debug);
4532   PlotCalibRunOverlay( canvas1DRunsOverlay, 5, sumCalibs, textSizeRel, 
4533                     Form("%s/HGScaleWidthSummary.%s",outputDirPlots.Data(),plotSuffix.Data()), it->second,"", debug);
4534 
4535   
4536   
4537   if (typeRO == ReadOut::Type::Caen){
4538     canvas2DCorr->SetLogz(0);
4539     PlotSimple2D( canvas2DCorr, hspectraLGMaxVsLayer, -10000, -10000, textSizeRel, Form("%s/LG_MaxMip.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true, Form( "#LT Max_{LG} #GT = %.1f", averageScaleUpdatedLow));
4540     PlotSimple2D( canvas2DCorr, hspectraLGFWHMVsLayer, -10000, -10000, textSizeRel, Form("%s/LG_FWHMMip.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true, Form( "#LT FWHM_{LG} #GT = %.1f", meanFWHMLG));
4541     PlotSimple2D( canvas2DCorr, hspectraLGLMPVVsLayer, -10000, -10000, textSizeRel, Form("%s/LG_LandMPVMip.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
4542     PlotSimple2D( canvas2DCorr, hspectraLGLSigmaVsLayer, -10000, -10000, textSizeRel, Form("%s/LG_LandSigMip.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
4543     PlotSimple2D( canvas2DCorr, hspectraLGGSigmaVsLayer, -10000, -10000, textSizeRel, Form("%s/LG_GaussSigMip.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
4544     
4545     PlotSimple1D(canvas1DRunsOverlay, hRatioMaxLGCalcLG, -10000, -10000, textSizeRel, 
4546               Form("%s/RatioMaxLGCalcLG.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, Form("%d/%d cells, #mu = %.2f", (Int_t)hRatioMaxLGCalcLG->GetEntries(), setup->GetNActiveCells(), hRatioMaxLGCalcLG->GetMean() ));
4547     PlotSimple1D(canvas1DRunsOverlay, hRatioMaxLGCalcAlterLG, -10000, -10000, textSizeRel, 
4548               Form("%s/RatioMaxLGCalcAlterLG.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, Form("%d/%d cells, #mu = %.2f", (Int_t)hRatioMaxLGCalcAlterLG->GetEntries(), setup->GetNActiveCells(), hRatioMaxLGCalcAlterLG->GetMean() ));
4549     PlotSimple1D(canvas1DRunsOverlay, hRatioMaxLGHG, -10000, -10000, textSizeRel, 
4550               Form("%s/RatioMaxLGHG.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, Form("%d/%d cells, #mu = %.2f", (Int_t)hRatioMaxLGHG->GetEntries(), setup->GetNActiveCells(), hRatioMaxLGHG->GetMean() ));
4551 
4552     PlotCalibRunOverlay( canvas1DRunsOverlay, 6, sumCalibs, textSizeRel, 
4553                         Form("%s/LGScaleSummary.%s",outputDirPlots.Data(),plotSuffix.Data()), it->second, "", debug);
4554     PlotCalibRunOverlay( canvas1DRunsOverlay, 7, sumCalibs, textSizeRel, 
4555                         Form("%s/LGScaleWidthSummary.%s",outputDirPlots.Data(),plotSuffix.Data()), it->second, "", debug);
4556 
4557     PlotCalibRunOverlay( canvas1DRunsOverlay, 8, sumCalibs, textSizeRel, 
4558                         Form("%s/LGHGCorr.%s",outputDirPlots.Data(),plotSuffix.Data()), it->second, "", debug);
4559     PlotCalibRunOverlay( canvas1DRunsOverlay, 9, sumCalibs, textSizeRel, 
4560                         Form("%s/HGLGCorr.%s",outputDirPlots.Data(),plotSuffix.Data()), it->second, "", debug);
4561     PlotCalibRunOverlay( canvas1DRunsOverlay, 10, sumCalibs, textSizeRel, 
4562                         Form("%s/LGScaleCalcSummary.%s",outputDirPlots.Data(),plotSuffix.Data()), it->second,"", debug);  
4563     PlotCalibRunOverlay( canvas1DRunsOverlay, 11, sumCalibs, textSizeRel, 
4564                         Form("%s/LGHGOffsetCorr.%s",outputDirPlots.Data(),plotSuffix.Data()), it->second, "", debug);
4565     PlotCalibRunOverlay( canvas1DRunsOverlay, 12, sumCalibs, textSizeRel, 
4566                         Form("%s/HGLGOffsetCorr.%s",outputDirPlots.Data(),plotSuffix.Data()), it->second, "", debug);
4567 
4568   }
4569 
4570   Double_t maxHG          = ReturnMipPlotRangeDepVov(calib.GetVov(),true, typeRO)*nSampleHGCROCInt;
4571   Double_t minHG          = ReturnMipMinPlotRangeDepVov(calib.GetVov(),true, typeRO);
4572   Double_t maxLG          = ReturnMipPlotRangeDepVov(calib.GetVov(),false, typeRO);
4573   Double_t maxTriggPPlot  = maxHG*2;
4574   Int_t textSizePixel     = 30;
4575   if (typeRO != ReadOut::Type::Caen)
4576     maxTriggPPlot = 150;
4577 
4578   //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
4579   // Single layer plotting
4580   //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
4581   MultiCanvas panelPlot(detConf, "ImpScale");
4582   bool init1D = panelPlot.Initialize(1);
4583     
4584   std::cout << "plotting single layers" << std::endl;
4585   panelPlot.PlotMipWithFits( hSpectra, hSpectraTrigg, 1, minHG, maxHG, 1.2, 
4586                               Form("%s/MIP_HG" ,outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, skipPlotLayer);
4587   panelPlot.PlotTriggerPrim( hSpectraTrigg, averageScalePerTile, factorMinTrigg, factorMaxTrigg, 0, maxTriggPPlot, 1.2,
4588                             Form("%s/TriggPrimitive" ,outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, skipPlotLayer);
4589   if (typeRO == ReadOut::Type::Caen){
4590     panelPlot.PlotMipWithFits( hSpectra, hSpectraTrigg, 0, -20, maxLG, 1.2, 
4591                               Form("%s/MIP_LG" ,outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, skipPlotLayer );
4592   }
4593   std::cout << "done plotting" << std::endl;
4594 
4595   //==================================================================================
4596   // Single tile plotting
4597   //==================================================================================
4598   if (ExtPlot > 2){
4599     TString outputDirPlotsSingle = Form("%s/SingleTiles",outputDirPlots.Data());
4600     gSystem->Exec("mkdir -p "+outputDirPlotsSingle);
4601 
4602     
4603     TCanvas* canvasSTile = new TCanvas("canvasSingleTile","",0,0,1600,1300);  // gives the page size
4604     DefaultCanvasSettings( canvasSTile, 0.08, 0.01, 0.01, 0.082);
4605 
4606     int counter = 0;
4607     for(ithSpectraTrigg=hSpectraTrigg.begin(); ithSpectraTrigg!=hSpectraTrigg.end(); ++ithSpectraTrigg){
4608       counter++;
4609       long cellID     = ithSpectraTrigg->second.GetCellID();
4610       int row = setup->GetRow(cellID);
4611       int col = setup->GetColumn(cellID);
4612       int lay = setup->GetLayer(cellID);
4613       int mod = setup->GetModule(cellID);
4614 
4615       PlotMipWithFitsSingleTile (canvasSTile, 0.95,  0.95, Double_t(textSizePixel)*2/1600., textSizePixel*2, 
4616                                 hSpectra, hSpectraTrigg, true,  -100, maxHG, 1.2, cellID,  Form("%s/MIP_HG_Tile_M%02d_L%02d_R%02d_C%02d.%s" ,outputDirPlotsSingle.Data(), mod, lay, row, col, plotSuffix.Data()), it->second);
4617     }
4618   }
4619   return true;
4620 } // end GetImprovedScaling()
4621 
4622 //***********************************************************************************************
4623 //*********************** strip noise from sample and fit ***************************************
4624 //***********************************************************************************************
4625 bool Analyses::GetNoiseSampleAndRefitPedestal(void){
4626   std::cout<<"GetNoiseSampleAndRefitPedestal"<<std::endl;
4627   // find detector config
4628   DetConf::Type detConf = setup->GetDetectorConfig();
4629 
4630   std::map<int,RunInfo> ri=readRunInfosFromFile(RunListInputName.Data(),debug,0);
4631   
4632   std::map<int,TileSpectra> hSpectra;
4633   std::map<int,TileSpectra> hSpectraTrigg;
4634   std::map<int, TileSpectra>::iterator ithSpectra;
4635   std::map<int, TileSpectra>::iterator ithSpectraTrigg;
4636   
4637   // create output file for histos
4638   if (!CreateOutputRootHistFile()) return false;
4639 
4640   // setup trigger sel
4641   double factorMinTrigg   = 0.5;
4642   if(yearData == 2023)
4643     factorMinTrigg        = 0.1;
4644   // create HG and LG histo's per channel
4645   TH2D* hspectraHGvsCellID      = new TH2D( "hNoiseTriggeredSpectraHG_vsCellID","Noise trigg ADC spectrum High Gain vs CellID; cell ID; ADC_{HG} (arb. units) ",
4646                                             setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5, 4000,0,4000);
4647   hspectraHGvsCellID->SetDirectory(0);
4648   TH2D* hspectraLGvsCellID      = new TH2D( "hNoiseTriggeredSpectraLG_vsCellID","Noise trigg ADC spectrum Low Gain vs CellID; cell ID; ADC_{LG} (arb. units)  ",
4649                                             setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5, 4000,0,4000);
4650   hspectraLGvsCellID->SetDirectory(0);
4651   
4652   RootOutputHist->mkdir("IndividualCells");
4653   RootOutputHist->mkdir("IndividualCellsTrigg");
4654   RootOutputHist->cd("IndividualCellsTrigg");  
4655   
4656   //***********************************************************************************************
4657   //************************* first pass over tree to extract spectra *****************************
4658   //***********************************************************************************************  
4659   TcalibIn->GetEntry(0);
4660   // check whether calib should be overwritten based on external text file
4661   if (OverWriteCalib){
4662     calib.ReadCalibFromTextFile(ExternalCalibFile,debug);
4663   }
4664   
4665   int evts=TdataIn->GetEntries();
4666   int runNr = -1;
4667   int actCh = 0;
4668   double averageScale     = calib.GetAverageScaleHigh(actCh);
4669   double averageScaleLow  = calib.GetAverageScaleLow();
4670   std::cout << "average HG mip: " << averageScale << " LG mip: "<< averageScaleLow << std::endl;
4671   for(int i=0; i<evts; i++){
4672     TdataIn->GetEntry(i);
4673     if (i == 0)runNr = event.GetRunNumber();
4674     TdataIn->GetEntry(i);
4675     if (i%5000 == 0 && i > 0 && debug > 0) std::cout << "Reading " <<  i << " / " << evts << " events" << std::endl;
4676     for(int j=0; j<event.GetNTiles(); j++){
4677       Caen* aTile=(Caen*)event.GetTile(j);
4678       if (i == 0 && debug > 2) std::cout << ((TString)setup->DecodeCellID(aTile->GetCellID())).Data() << std::endl;
4679       long currCellID = aTile->GetCellID();
4680       
4681       // read current tile
4682       ithSpectraTrigg=hSpectraTrigg.find(aTile->GetCellID());
4683       // estimate local muon trigger
4684       bool localNoiseTrigg = event.InspectIfNoiseTrigg(currCellID, averageScale, factorMinTrigg);
4685       
4686       if(ithSpectraTrigg!=hSpectraTrigg.end()){
4687         ithSpectraTrigg->second.FillTrigger(aTile->GetLocalTriggerPrimitive());
4688       } else {
4689         RootOutputHist->cd("IndividualCellsTrigg");
4690         hSpectraTrigg[currCellID]=TileSpectra("mipTrigg",currCellID,calib.GetTileCalib(currCellID),event.GetROtype(), nSampleHGCROCInt, debug);
4691         hSpectraTrigg[currCellID].FillTrigger(aTile->GetLocalTriggerPrimitive());;
4692         RootOutput->cd();
4693       }
4694       
4695       ithSpectra=hSpectra.find(aTile->GetCellID());
4696       if (ithSpectra!=hSpectra.end()){
4697         ithSpectra->second.FillSpectraCAEN(aTile->GetADCLow(),aTile->GetADCHigh());
4698       } else {
4699         RootOutputHist->cd("IndividualCells");
4700         hSpectra[currCellID]=TileSpectra("mip1st",currCellID,calib.GetTileCalib(currCellID),event.GetROtype(), nSampleHGCROCInt, debug);
4701         hSpectra[aTile->GetCellID()].FillSpectraCAEN(aTile->GetADCLow(),aTile->GetADCHigh());;
4702 
4703         RootOutput->cd();
4704       }
4705     
4706       // only fill tile spectra if X surrounding tiles on average are compatible with pure noise
4707       if (localNoiseTrigg){
4708         aTile->SetLocalTriggerBit(2);
4709         ithSpectraTrigg=hSpectraTrigg.find(aTile->GetCellID());
4710         ithSpectraTrigg->second.FillSpectraCAEN(aTile->GetADCLow(),aTile->GetADCHigh());
4711         
4712         hspectraHGvsCellID->Fill(aTile->GetCellID(), aTile->GetADCHigh());
4713         hspectraLGvsCellID->Fill(aTile->GetCellID(), aTile->GetADCLow());
4714       }
4715     }
4716     RootOutput->cd();
4717     TdataOut->Fill();
4718   }
4719   TdataOut->Write();
4720   TsetupIn->CloneTree()->Write();
4721   
4722   //***********************************************************************************************
4723   //***** Monitoring histos for fits results of 2nd iteration ******************
4724   //***********************************************************************************************
4725   RootOutputHist->cd();
4726   int maxChannelPerLayer             = (setup->GetNMaxColumn()+1)*(setup->GetNMaxRow()+1)*(setup->GetNMaxModule()+1);
4727   int maxChannelPerLayerSingleMod    = (setup->GetNMaxColumn()+1)*(setup->GetNMaxRow()+1);
4728 
4729   // monitoring trigger 
4730   TH2D* hnoiseTriggers              = new TH2D( "hnoiseTriggers","muon triggers; layer; brd channel; counts ",
4731                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
4732   hnoiseTriggers->SetDirectory(0);
4733   TH1D* hMeanPedHGvsCellID      = new TH1D( "hMeanPedHG_vsCellID","mean Ped High Gain vs CellID ; cell ID; #mu_{noise, HG} (arb. units) ",
4734                                             setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5);
4735   hMeanPedHGvsCellID->SetDirectory(0);
4736   TH2D* hspectraHGMeanVsLayer   = new TH2D( "hspectraHGMeanVsLayer","Mean Ped High Gain vs CellID; layer; brd channel; #mu_{Ped HG} (arb. units) ",
4737                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
4738   hspectraHGMeanVsLayer->SetDirectory(0);
4739   TH2D* hspectraHGSigmaVsLayer  = new TH2D( "hspectraHGSigmaVsLayer","Mean Ped High Gain vs CellID; layer; brd channel; #sigma_{Ped HG} (arb. units) ",
4740                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
4741   hspectraHGSigmaVsLayer->SetDirectory(0);
4742   TH1D* hMeanPedLGvsCellID      = new TH1D( "hMeanPedLG_vsCellID","mean Ped Low Gain vs CellID ; cell ID; #mu_{noise, LG} (arb. units) ",
4743                                             setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5);
4744   hMeanPedLGvsCellID->SetDirectory(0);
4745   TH2D* hspectraLGMeanVsLayer   = new TH2D( "hspectraLGMeanVsLayer","Mean Ped Low Gain vs CellID; layer; brd channel; #mu_{PED LG} (arb. units) ",
4746                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
4747   hspectraLGMeanVsLayer->SetDirectory(0);
4748   TH2D* hspectraLGSigmaVsLayer  = new TH2D( "hspectraLGSigmaVsLayer","Mean Ped Low Gain vs CellID; layer; brd channel; #sigma_{Ped LG} (arb. units)",
4749                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
4750   hspectraLGSigmaVsLayer->SetDirectory(0);
4751 
4752   if ( debug > 0)
4753     std::cout << "============================== starting fitting" << std::endl;
4754 
4755   int currCells = 0;
4756   double* parameters    = new double[6];
4757   for(ithSpectraTrigg=hSpectraTrigg.begin(); ithSpectraTrigg!=hSpectraTrigg.end(); ++ithSpectraTrigg){
4758     for (int p = 0; p < 6; p++){
4759       parameters[p]   = 0;
4760     }
4761 
4762     if (currCells%20 == 0 && currCells > 0 && debug > 0)
4763       std::cout << "============================== cell " <<  currCells << " / " << hSpectraTrigg.size() << " cells" << std::endl;
4764     currCells++;
4765     if ( debug > 2) std::cout << ((TString)setup->DecodeCellID(ithSpectraTrigg->second.GetCellID())).Data() << std::endl;
4766     ithSpectraTrigg->second.FitNoise(parameters, yearData, true);
4767     hMeanPedHGvsCellID->SetBinContent(hMeanPedHGvsCellID->FindBin(ithSpectraTrigg->second.GetCellID()), parameters[4]);
4768     hMeanPedHGvsCellID->SetBinError  (hMeanPedHGvsCellID->FindBin(ithSpectraTrigg->second.GetCellID()), parameters[6]);
4769     hMeanPedLGvsCellID->SetBinContent(hMeanPedLGvsCellID->FindBin(ithSpectraTrigg->second.GetCellID()), parameters[0]);
4770     hMeanPedLGvsCellID->SetBinError  (hMeanPedLGvsCellID->FindBin(ithSpectraTrigg->second.GetCellID()), parameters[2]);
4771     
4772     int layer           = setup->GetLayer(ithSpectraTrigg->second.GetCellID());
4773     int chInLayer       = setup->GetChannelInLayerFull(ithSpectraTrigg->second.GetCellID(),detConf);
4774     hspectraHGMeanVsLayer->SetBinContent(hspectraHGMeanVsLayer->FindBin(layer,chInLayer), parameters[4]);
4775     hspectraHGMeanVsLayer->SetBinError(hspectraHGMeanVsLayer->FindBin(layer,chInLayer), parameters[5]);
4776     hspectraHGSigmaVsLayer->SetBinContent(hspectraHGSigmaVsLayer->FindBin(layer,chInLayer), parameters[6]);
4777     hspectraHGSigmaVsLayer->SetBinError(hspectraHGSigmaVsLayer->FindBin(layer,chInLayer), parameters[7]);
4778     hspectraLGMeanVsLayer->SetBinContent(hspectraLGMeanVsLayer->FindBin(layer,chInLayer), parameters[0]);
4779     hspectraLGMeanVsLayer->SetBinError(hspectraLGMeanVsLayer->FindBin(layer,chInLayer), parameters[1]);
4780     hspectraLGSigmaVsLayer->SetBinContent(hspectraLGSigmaVsLayer->FindBin(layer,chInLayer), parameters[2]);
4781     hspectraLGSigmaVsLayer->SetBinError(hspectraLGSigmaVsLayer->FindBin(layer,chInLayer), parameters[3]);
4782     
4783     hnoiseTriggers->SetBinContent(hnoiseTriggers->FindBin(layer,chInLayer), ithSpectraTrigg->second.GetHG()->GetEntries());
4784   }
4785   if ( debug > 0)
4786     std::cout << "============================== done fitting" << std::endl;
4787   
4788   RootOutput->cd();
4789   
4790   if (IsCalibSaveToFile()){
4791     TString fileCalibPrint = RootOutputName;
4792     fileCalibPrint         = fileCalibPrint.ReplaceAll(".root","_calib.txt");
4793     calib.PrintCalibToFile(fileCalibPrint);
4794   }
4795 
4796 
4797   TcalibOut->Fill();
4798   TcalibOut->Write();
4799   
4800   RootOutput->Write();
4801   RootOutput->Close();
4802 
4803 
4804   RootOutputHist->cd("IndividualCellsTrigg");
4805     for(ithSpectra=hSpectraTrigg.begin(); ithSpectra!=hSpectraTrigg.end(); ++ithSpectra){
4806       ithSpectra->second.Write(true);
4807     }
4808   RootOutputHist->cd();
4809     
4810     hMeanPedHGvsCellID->Write();
4811     hMeanPedLGvsCellID->Write();
4812     hspectraHGMeanVsLayer->Write();
4813     hspectraHGSigmaVsLayer->Write();
4814     hspectraLGMeanVsLayer->Write(); 
4815     hspectraLGSigmaVsLayer->Write();
4816     hspectraHGvsCellID->Write();
4817     hspectraLGvsCellID->Write();
4818         
4819     hnoiseTriggers->Write();
4820   // close open root files
4821   RootOutputHist->Write();
4822   RootOutputHist->Close();
4823 
4824   RootInput->Close();
4825 
4826   // Get run info object
4827   std::map<int,RunInfo>::iterator it=ri.find(runNr);
4828   
4829   // create directory for plot output
4830   TString outputDirPlots = GetPlotOutputDir();
4831   gSystem->Exec("mkdir -p "+outputDirPlots);
4832   
4833   //**********************************************************************
4834   // Create canvases for channel overview plotting
4835   //**********************************************************************
4836   Double_t textSizeRel = 0.035;
4837   StyleSettingsBasics("pdf");
4838   SetPlotStyle();
4839 
4840   TCanvas* canvas2DCorr = new TCanvas("canvasCorrPlots","",0,0,1450,1300);  // gives the page size
4841   DefaultCanvasSettings( canvas2DCorr, 0.08, 0.13, 0.045, 0.07);
4842 
4843   canvas2DCorr->SetLogz(0);
4844   PlotSimple2D( canvas2DCorr, hspectraHGMeanVsLayer, -10000, -10000, textSizeRel, Form("%s/HG_NoiseMean.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true );
4845   PlotSimple2D( canvas2DCorr, hspectraHGSigmaVsLayer, -10000, -10000, textSizeRel, Form("%s/HG_NoiseSigma.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
4846   PlotSimple2D( canvas2DCorr, hspectraLGMeanVsLayer, -10000, -10000, textSizeRel, Form("%s/LG_NoiseMean.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
4847   PlotSimple2D( canvas2DCorr, hspectraLGSigmaVsLayer, -10000, -10000, textSizeRel, Form("%s/LG_NoiseSigma.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
4848   canvas2DCorr->SetLogz(1);
4849   PlotSimple2D( canvas2DCorr, hspectraHGvsCellID, -10000, -10000, textSizeRel, Form("%s/HG_Noise.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
4850   PlotSimple2D( canvas2DCorr, hspectraLGvsCellID, -10000, -10000, textSizeRel, Form("%s/LG_Noise.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
4851   
4852   PlotSimple2D( canvas2DCorr, hnoiseTriggers, -10000, -10000, textSizeRel, Form("%s/LG_Noise.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true, Form( "evt. coll = %d", evts));
4853   
4854   //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
4855   // Multipanel plotting
4856   //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
4857   MultiCanvas panelPlot(detConf, "NoiseSample");
4858   bool init1D = panelPlot.Initialize(1);
4859     
4860   panelPlot.PlotNoiseAdvWithFits(hSpectra, hSpectraTrigg, 1, 0, 450, 1.2, 
4861                                   Form("%s/NoiseTrigg_HG" ,outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib);
4862   
4863 
4864   
4865   return true;
4866 }
4867 
4868 //***********************************************************************************************
4869 //*********************** Evaluate local triggers only and store information ********************
4870 //***********************************************************************************************
4871 bool Analyses::RunEvalLocalTriggers(void){
4872   std::cout<<"EvalLocalTriggers"<<std::endl;
4873 
4874   // find detector config
4875   DetConf::Type detConf   = setup->GetDetectorConfig();
4876   
4877   // read full run list
4878   std::map<int,RunInfo> ri=readRunInfosFromFile(RunListInputName.Data(),debug,0);
4879 
4880   RootOutput->cd();
4881   // reading calib object
4882   std::cout << "starting to run trigger eval: " << TcalibIn <<  "\t" << TcalibIn->GetEntry(0) << std::endl;
4883   TcalibIn->GetEntry(0);
4884   // check whether calib should be overwritten based on external text file
4885   if (OverWriteCalib){
4886     calib.ReadCalibFromTextFile(ExternalCalibFile,debug);
4887   }
4888   
4889   // reading first event in tree to extract runnumber & RO-type
4890   TdataIn->GetEntry(0);
4891   int evts              = TdataIn->GetEntries();
4892   Int_t runNr           = event.GetRunNumber();
4893   ReadOut::Type typeRO  = event.GetROtype();
4894   // reset calib object event infos
4895   std::cout<< "original run numbers calib: "<<calib.GetRunNumber() << "\t" << calib.GetRunNumberPed() << "\t" << calib.GetRunNumberMip() << std::endl;
4896   calib.SetRunNumber(runNr);
4897   calib.SetBeginRunTime(event.GetBeginRunTimeAlt());
4898   std::cout<< "reset run numbers calib: "<< calib.GetRunNumber() << "\t" << calib.GetRunNumberPed() << "\t" << calib.GetRunNumberMip() << std::endl;
4899   
4900   // getting averages from calib objects
4901   int actCh1st = 0;
4902   double averageScale = calib.GetAverageScaleHigh(actCh1st);
4903   int actChalt                  = 0;
4904   double averageNTiles          = 0.;
4905   double averageScalePerTile    = calib.GetAverageScaleHighPerSingleLayer(actChalt, averageNTiles);
4906   double avLGHGCorr             = calib.GetAverageLGHGCorr();
4907   double avLGHGCorrOff          = calib.GetAverageLGHGCorrOff();
4908   std::cout << "average HG mip: " << averageScale << "\t per tile: " <<  averageScalePerTile << "\t active ch: "<< actCh1st << "\t av NTiles/seg: " << averageNTiles << std::endl;
4909 
4910   int actCh1stL               = 0;
4911   double averageScaleL        = 0;
4912   int actChaltL               = 0;
4913   double averageNTilesL       = 0.;
4914   double averageScaleLPerTile = 0;
4915   if (typeRO == ReadOut::Type::Caen ){
4916     averageScaleL = calib.GetAverageScaleLow(actCh1stL);
4917     averageScaleLPerTile     = calib.GetAverageScaleLowPerSingleLayer(actChaltL, averageNTilesL);
4918     std::cout << "average LG mip: " << averageScaleL << "\t per tile: " <<  averageScaleLPerTile << "\t active ch: "<< actCh1stL << "\t av NTiles/seg: " << averageNTilesL << std::endl;
4919   }
4920   
4921   // Set correct calib scale for trigger eval
4922   double calibScale           = 0;
4923   if (typeRO == ReadOut::Type::Caen ){
4924     // LG scale as evaluated from fits
4925     if (calibOption == 0){
4926       calibScale  = averageScaleLPerTile;
4927       std::cout << "Estimating triggers using calib option " << calibOption << ". This uses the average of all LG evaluated fits, averages is: " << calibScale << std::endl;
4928     // LG scale calc from HG
4929     } else if (calibOption == 1){
4930       calibScale  = (averageScalePerTile-avLGHGCorrOff)/avLGHGCorr;
4931       std::cout << "Estimating triggers using calib option " << calibOption << ". This uses the average of all HG evaluated fits and calculates LG equivalent, averages is: " << calibScale << std::endl;
4932     // HG scale as evaluated from fits
4933     } else if (calibOption >= 2){
4934       calibScale  = averageScalePerTile;
4935       std::cout << "Estimating triggers using calib option " << calibOption << ". This uses the average of all HG evaluated fits, averages is: " << calibScale << std::endl;
4936     } else {
4937       std::cout << "This calib option is unknown: " << calibOption << " *************** ABORTING!!!!" << std::endl;
4938       return false;
4939     }
4940   } else {
4941     calibScale  = averageScalePerTile;
4942     std::cout << " Calibrating using average ADC max fits, averages is: " << calibScale << std::endl;
4943   }
4944   //==================================================================================
4945   // setup waveform builder for HGCROC data
4946   //==================================================================================
4947   waveform_fit_base *waveform_builder = nullptr;
4948   if (GetHGCROCOptInteg() == 1 || GetHGCROCOptInteg() == 101){
4949     waveform_builder = new max_sample_fit_n_integ(GetHGCROCNSampleInteg());
4950   } else {
4951     waveform_builder = new max_sample_fit();
4952   }
4953   
4954   // setup local trigger sel
4955   TRandom3* rand    = new TRandom3();
4956   Int_t localTriggerTiles     = 4;
4957   if (yearData == 2023){
4958     localTriggerTiles         = 6;
4959   }
4960   double factorMinTrigg       = 0.8;
4961   double factorMinTriggNoise  = 0.2;
4962   double factorMaxTrigg       = 2.5;
4963   if (yearData == 2023){
4964     factorMinTrigg            = 0.9;
4965     factorMaxTrigg            = 2.;
4966   }
4967   
4968   // reset maximum number of events if requested
4969   if (maxEvents == -1){
4970     maxEvents = evts;
4971   } else {
4972     std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
4973     std::cout << "ATTENTION: YOU ARE RESETTING THE MAXIMUM NUMBER OF EVENTS TO BE PROCESSED TO: " << maxEvents << ". THIS SHOULD ONLY BE USED FOR TESTING!" << std::endl;
4974     std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
4975   }
4976   
4977   // set cout frequent
4978   int outCount                = 1000;
4979   if (evts < 10000)
4980     outCount  = 500;
4981   if (evts > 100000)
4982     outCount  = 5000;
4983   
4984   //==================================================================================
4985   // Create & setup general monitoring histograms
4986   //==================================================================================  
4987   // create output file for histos
4988   if (!CreateOutputRootHistFile()) return false;
4989   // 2D beam profile -EP
4990   int maxChannelPerLayer          = (setup->GetNMaxColumn()+1)*(setup->GetNMaxRow()+1)*(setup->GetNMaxModule()+1);
4991   int maxChannelPerLayerSingleMod = (setup->GetNMaxColumn()+1)*(setup->GetNMaxRow()+1);
4992   int thisbinxmax = setup->GetNMaxColumn()+1;   
4993   int thisbinymax = (int)(setup->GetNMaxRow()+1)*(setup->GetNMaxModule()+1);
4994   int thisbinzmax = (int)setup->GetNMaxLayer()+1;
4995   
4996   RootOutputHist->cd();
4997   // 2D beam profile front view
4998   TH2D* hMipTriggXY               = new TH2D( "hMipTriggXY", "MIP Triggers summed over layers; X (col); Y (row); Num triggers", 
4999                                               thisbinxmax, -0.5, thisbinxmax-0.5, thisbinymax, -0.5, thisbinymax-0.5); 
5000   hMipTriggXY->SetDirectory(0);
5001   // 3D beam profile -EP
5002   TH3D *hMipTriggXYZ              = new TH3D( "hMipTriggXYZ", "MIP Triggers; X (col); Z (layer); Y (row); Num triggers", 
5003                                               thisbinxmax, -0.5, thisbinxmax-0.5, thisbinzmax, -0.5, thisbinzmax-0.5, thisbinymax, -0.5, thisbinymax-0.5);
5004   hMipTriggXYZ->SetDirectory(0);
5005   // monitoring trigger 
5006   TH2D* hmipTriggers              = new TH2D( "hmipTriggers","muon triggers; layer; brd channel; counts ",
5007                                             setup->GetNMaxLayer()+1, -0.5, setup->GetNMaxLayer()+1-0.5, maxChannelPerLayer, -0.5, maxChannelPerLayer-0.5);
5008   hmipTriggers->SetDirectory(0);
5009   // monitoring triggers vs Cell ID
5010   TH1D* hMipTriggersGvsCellID     = new TH1D( "hMipTriggersGvsCellID","mip Triggers vs CellID ; cell ID; Nr. mip trigg ",
5011                                             setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5);
5012   hMipTriggersGvsCellID->SetDirectory(0);
5013 
5014   // create tileSpectra objects
5015   std::map<int,TileSpectra> hSpectra;
5016   std::map<int,TileSpectra> hSpectraTrigg;
5017   std::map<int, TileSpectra>::iterator ithSpectra;
5018   std::map<int, TileSpectra>::iterator ithSpectraTrigg;
5019   RootOutputHist->mkdir("IndividualCells");
5020   RootOutputHist->mkdir("IndividualCellsTrigg");
5021   RootOutputHist->cd("IndividualCellsTrigg");  
5022 
5023   //==================================================================================
5024   // Process input tree & evaulate new triggers
5025   //==================================================================================  
5026   for(int i=0; i<evts && i < maxEvents; i++){
5027     TdataIn->GetEntry(i);
5028     if (i%outCount == 0 && debug > 0) std::cout << "Reading " <<  i << " / " << evts << " events" << std::endl;
5029     
5030     //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5031     // Single tile processing
5032     //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5033     for(int j=0; j<event.GetNTiles(); j++){
5034 
5035       //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5036       // CAEN treatment
5037       //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++      
5038       if (typeRO == ReadOut::Type::Caen) {
5039         Caen* aTile=(Caen*)event.GetTile(j);      
5040         int currCellID = aTile->GetCellID();  
5041         // calculate trigger primitives
5042         if (EvalTriggerPrimitives) aTile->SetLocalTriggerPrimitive(event.CalculateLocalMuonTrigg(calib, rand, currCellID, localTriggerTiles, avLGHGCorr, calibOption));
5043         
5044         bool localMuonTrigg   = event.InspectIfLocalMuonTrigg(currCellID, calibScale, factorMinTrigg, factorMaxTrigg);
5045         bool localNoiseTrigg  = event.InspectIfNoiseTrigg(currCellID, calibScale, factorMinTriggNoise);
5046         aTile->SetLocalTriggerBit(0);
5047         if (localMuonTrigg) aTile->SetLocalTriggerBit(1);
5048         if (localNoiseTrigg) aTile->SetLocalTriggerBit(2);
5049         
5050       //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5051       // HGCROC treatment
5052       //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5053       } else if (typeRO == ReadOut::Type::Hgcroc) {
5054         Hgcroc* aTile=(Hgcroc*)event.GetTile(j);
5055         int currCellID = aTile->GetCellID();  
5056         
5057         //-------------------------------------------------------------------------------
5058         // possibly reevaluate waveform
5059         //-------------------------------------------------------------------------------
5060         if (GetHGCROCOptInteg() > 99){
5061           // pedestals
5062           double ped    = calib.GetPedestalMeanL(currCellID);
5063           double pedErr = calib.GetPedestalSigL(currCellID);
5064           if (ped == -1000){
5065             ped     = calib.GetPedestalMeanH(currCellID);
5066             pedErr  = calib.GetPedestalSigH(currCellID);
5067             if (ped == -1000){
5068               ped     = aTile->GetPedestal();
5069               pedErr  = 5;
5070             }
5071           }
5072           // reevaluate waveform
5073           waveform_builder->set_waveform(aTile->GetADCWaveform());
5074           waveform_builder->fit_with_average_ped(ped);
5075           aTile->SetIntegratedADC(waveform_builder->get_E());
5076           aTile->SetPedestal(waveform_builder->get_pedestal());
5077         }
5078       
5079         // calculate trigger primitives
5080         aTile->SetLocalTriggerPrimitive(event.CalculateLocalMuonTrigg(calib, rand, currCellID, localTriggerTiles, 0.,0));
5081         
5082         bool localMuonTrigg   = event.InspectIfLocalMuonTrigg(currCellID, calibScale, factorMinTrigg, factorMaxTrigg);
5083         // if (localMuonTrigg) std::cout << " triggered " << std::endl;
5084         bool localNoiseTrigg  = event.InspectIfNoiseTrigg(currCellID, calibScale, factorMinTriggNoise);
5085         
5086         // reset Local trigger bit
5087         aTile->SetLocalTriggerBit(0);
5088         // set trigger bit to muon
5089         if (localMuonTrigg){
5090           aTile->SetLocalTriggerBit(1);
5091           hMipTriggersGvsCellID->Fill(currCellID);
5092           
5093           int layer       = setup->GetLayer(currCellID);
5094           int chInLayer   = setup->GetChannelInLayerFull(currCellID,detConf);
5095           int row         = setup->GetRow(currCellID);
5096           int col         = setup->GetColumn(currCellID);
5097           int mod         = setup->GetModule(currCellID);
5098           
5099           hmipTriggers->Fill(layer,chInLayer);
5100           hMipTriggXY->Fill(col, (mod*2) + row);
5101           hMipTriggXYZ->Fill(col, layer, (mod*2) + row);
5102         }
5103         // set trigger bit to noise
5104         if (localNoiseTrigg) {
5105           aTile->SetLocalTriggerBit(2);
5106         }
5107           
5108         double adc = aTile->GetIntegratedADC();
5109         double tot = aTile->GetRawTOT();
5110         double toa = aTile->GetRawTOA();
5111 
5112         //-------------------------------------------------------------------------------
5113         // filling single tile spectra for monitoring
5114         //-------------------------------------------------------------------------------
5115         ithSpectraTrigg = hSpectraTrigg.find(currCellID);
5116         ithSpectra      = hSpectra.find(currCellID);
5117         
5118         // create tile sprectra object if not yet there for triggered cells & fill trigger primitives
5119         if(ithSpectraTrigg!=hSpectraTrigg.end()){
5120           ithSpectraTrigg->second.FillTrigger(aTile->GetLocalTriggerPrimitive());
5121         } else {
5122           RootOutputHist->cd("IndividualCellsTrigg");
5123           hSpectraTrigg[currCellID]=TileSpectra("mipTrigg",currCellID,calib.GetTileCalib(currCellID),event.GetROtype(), nSampleHGCROCInt, debug);
5124           hSpectraTrigg[currCellID].FillTrigger(aTile->GetLocalTriggerPrimitive());;
5125           RootOutput->cd();
5126         }
5127         // only fill tile spectra if 4 surrounding tiles on average are compatible with muon response
5128         if (localMuonTrigg){
5129           ithSpectraTrigg=hSpectraTrigg.find(currCellID);
5130           ithSpectraTrigg->second.FillHGCROC(adc, toa, tot);
5131         }
5132         
5133         // create tile sprectra object if not yet there for all cells & fill 
5134         if (ithSpectra!=hSpectra.end()){
5135           ithSpectra->second.FillHGCROC(adc, toa, tot);
5136         } else {
5137           RootOutputHist->cd("IndividualCells");
5138           hSpectra[currCellID]=TileSpectra("mip1st",currCellID,calib.GetTileCalib(currCellID),event.GetROtype(), nSampleHGCROCInt,  debug);
5139           hSpectra[currCellID].FillHGCROC(adc, toa, tot);
5140           RootOutput->cd();
5141         }
5142       }
5143     }
5144     RootOutput->cd();
5145     TdataOut->Fill();
5146   }
5147   
5148   //==================================================================================
5149   // Write tree output file
5150   //==================================================================================
5151   RootOutput->cd();
5152     TdataOut->Write();
5153     TsetupIn->CloneTree()->Write();
5154     
5155     if (IsCalibSaveToFile()){
5156       TString fileCalibPrint = RootOutputName;
5157       fileCalibPrint         = fileCalibPrint.ReplaceAll(".root","_calib.txt");
5158       calib.PrintCalibToFile(fileCalibPrint);
5159     }
5160     
5161     TcalibOut->Fill();
5162     TcalibOut->Write();
5163   RootOutput->Close();
5164   RootInput->Close();      
5165   
5166   //==================================================================================
5167   // Set up general plotting variables
5168   //==================================================================================
5169   // Get run info object
5170   std::map<int,RunInfo>::iterator it=ri.find(runNr);
5171   // create directory for plot output
5172   TString outputDirPlots  = GetPlotOutputDir();
5173   gSystem->Exec("mkdir -p "+outputDirPlots);
5174   
5175   Double_t textSizeRel = 0.035;
5176   StyleSettingsBasics("pdf");
5177   SetPlotStyle();  
5178 
5179   Double_t maxHG          = ReturnMipPlotRangeDepVov(calib.GetVov(),true, typeRO);
5180   Double_t minHG          = ReturnMipMinPlotRangeDepVov(calib.GetVov(),true, typeRO);
5181   Double_t maxLG          = ReturnMipPlotRangeDepVov(calib.GetVov(),false, typeRO);
5182   Double_t maxTriggPPlot  = maxHG*2;
5183   Int_t textSizePixel     = 30;
5184   if (typeRO != ReadOut::Type::Caen)
5185     maxTriggPPlot = 150;
5186 
5187   //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
5188   // Single layer plotting
5189   //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
5190   MultiCanvas panelPlot(detConf, "Skim");
5191   bool init1D = panelPlot.Initialize(1);
5192     
5193   std::cout << "plotting single layers" << std::endl;
5194   panelPlot.PlotMipWithFits( hSpectra, hSpectraTrigg, 1, minHG, maxHG, 1.2, 
5195                               Form("%s/MIP_HG" ,outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, skipPlotLayer);
5196   panelPlot.PlotTriggerPrim( hSpectraTrigg, averageScalePerTile, factorMinTrigg, factorMaxTrigg, 0, maxTriggPPlot, 1.2,
5197                             Form("%s/TriggPrimitive" ,outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, skipPlotLayer);
5198   std::cout << "done plotting" << std::endl;
5199 
5200   //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
5201   // Overview plots
5202   //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
5203   TCanvas* canvas2DCorr = new TCanvas("canvasCorrPlots","",0,0,1450,1300);  // gives the page size
5204   DefaultCanvasSettings( canvas2DCorr, 0.08, 0.13, 0.045, 0.07);
5205   TCanvas* canvas1DSimple = new TCanvas("canvas1DSimple","",0,0,1450,1300);  // gives the page size
5206   DefaultCanvasSettings( canvas1DSimple, 0.08, 0.03, 0.03, 0.07);
5207   
5208   std::cout << "plotting overview" << std::endl;
5209   PlotSimple2D( canvas2DCorr, hmipTriggers, -10000, -10000, textSizeRel, 
5210                 Form("%s/MipTrigger.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
5211   PlotSimple2D( canvas2DCorr, hMipTriggXY, -10000, -10000, textSizeRel, 
5212                 Form("%s/MipTriggerXY.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
5213   PlotSimple1D(canvas1DSimple, hMipTriggersGvsCellID, -10000, -10000, textSizeRel, 
5214               Form("%s/MuonTriggVsCellID.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1);
5215   TH1D* hMipTriggersGvsCellIDPerEvt = (TH1D*)hMipTriggersGvsCellID->Clone("hMipTriggersGvsCellIDPerEvt");
5216   hMipTriggersGvsCellIDPerEvt->Scale(1./evts);
5217   hMipTriggersGvsCellIDPerEvt->GetYaxis()->SetTitle("#mu triggers/event");
5218   PlotSimple1D(canvas1DSimple, hMipTriggersGvsCellIDPerEvt, -10000, -10000, textSizeRel, 
5219               Form("%s/MuonTriggPerEventVsCellID.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1);
5220 
5221   //==================================================================================
5222   // Write output hist file
5223   //==================================================================================
5224   RootOutputHist->cd();
5225     hMipTriggersGvsCellID->Write();
5226     hMipTriggersGvsCellIDPerEvt->Write();
5227     hmipTriggers->Write();
5228     hMipTriggXY->Write();
5229     hMipTriggXYZ->Write();
5230     
5231   RootOutputHist->cd("IndividualCellsTrigg");
5232     for(ithSpectraTrigg=hSpectraTrigg.begin(); ithSpectraTrigg!=hSpectraTrigg.end(); ++ithSpectraTrigg){
5233       ithSpectraTrigg->second.Write(true);
5234     }
5235   RootOutputHist->cd("IndividualCells");
5236     for(ithSpectra=hSpectra.begin(); ithSpectra!=hSpectra.end(); ++ithSpectra){
5237       ithSpectra->second.Write(true);
5238     }
5239   RootOutputHist->Write();
5240   RootOutputHist->Close();
5241   
5242   return true;
5243 
5244 }
5245 
5246 //***********************************************************************************************
5247 //*********************** Calibration routine ***************************************************
5248 //***********************************************************************************************
5249 bool Analyses::Calibrate(void){
5250   std::cout<<"Calibrate"<<std::endl;
5251 
5252   std::map<int,RunInfo> ri=readRunInfosFromFile(RunListInputName.Data(),debug,0);
5253 
5254   // Find detector config
5255   DetConf::Type detConf = setup->GetDetectorConfig();
5256   
5257   //=============================================================================================
5258   // Reset calibs if necessary
5259   //=============================================================================================
5260   std::cout << "starting to run calibration: " << TcalibIn <<  "\t" << TcalibIn->GetEntry(0) << std::endl;
5261   TcalibIn->GetEntry(0);
5262   // check whether calib should be overwritten based on external text file
5263   if (OverWriteCalib){
5264     calib.ReadCalibFromTextFile(ExternalCalibFile,debug);
5265   }
5266   // set external bad channel map
5267   if (CalcBadChannel == 1){
5268     calib.ReadExternalBadChannelMap(ExternalBadChannelMap, debug);
5269   }
5270   // add ToA offsets for half asics to calib objects if available
5271   if (ExternalToACalibOffSetFile.CompareTo("") != 0 ){
5272     calib.ReadExternalToAOffsets(ExternalToACalibOffSetFile,debug);
5273   }
5274 
5275   // reading first event in tree to extract runnumber & RO-type
5276   TdataIn->GetEntry(0);
5277   Int_t runNr           = event.GetRunNumber();
5278   ReadOut::Type typeRO  = event.GetROtype();
5279   std::cout<< "original run numbers calib: "<<calib.GetRunNumber() << "\t" << calib.GetRunNumberPed() << "\t" << calib.GetRunNumberMip() << std::endl;
5280   calib.SetRunNumber(runNr);
5281   calib.SetBeginRunTime(event.GetBeginRunTimeAlt());
5282   std::cout<< "reset run numbers calib: "<< calib.GetRunNumber() << "\t" << calib.GetRunNumberPed() << "\t" << calib.GetRunNumberMip() << std::endl;
5283   
5284   // Get run info object
5285   std::map<int,RunInfo>::iterator it=ri.find(runNr);
5286 
5287   //=============================================================================================
5288   // Create output histos
5289   //=============================================================================================
5290   if (!CreateOutputRootHistFile()) return false;
5291   
5292   TH2D* hspectraHGvsCellID          = nullptr;      // all cells raw ADC (HG - CAEN, ADC HGCROC) spectrum vs Cell ID
5293   TH2D* hspectraHGCorrvsCellID      = nullptr;      // all cells pedestal corrected ADC (HG - CAEN, ADC HGCROC) spectrum vs Cell ID
5294   TH2D* hspectraHGCorrvsCellIDNoise = nullptr;      // noise trigger flagged pedestal  ADC (HG - CAEN, ADC HGCROC) spectrum vs Cell ID
5295   TH1D* hSaturatedADCvsCellID       = nullptr;      // saturated HG ADC (CAEN)/ ADC (HGCROC) frequency vs cellID
5296   TH1D* hSaturatedADC               = nullptr;      // saturated HG ADC (CAEN)/ ADC (HGCROC) frequency per event
5297   
5298   // CAEN only
5299   TH2D* hspectraLGvsCellID          = nullptr;      // all cells raw LG ADC (CAEN) spectrum vs Cell ID
5300   TH2D* hspectraLGCorrvsCellID      = nullptr;      // all cells pedestal correctected LG ADC (CAEN) spectrum vs Cell ID
5301   TH2D* hspectraLGCorrvsCellIDNoise = nullptr;      // noise trigger flagged pedestal correctected LG ADC (CAEN) spectrum vs Cell ID
5302   TH1D* hSaturatedLGvsCellID        = nullptr;      // saturated LG ADC (CAEN) frequency vs cellID
5303   TH1D* hSaturatedLG                = nullptr;      // saturated LG ADC (CAEN) frequency per event
5304   TH1D* hLGHGCorrOutsideBoundCellID = nullptr;      // LG/HG outside expectation frequency vs cellID
5305   TH1D* hNCellsLGHGCorrOutsideBound = nullptr;      // Nr. of cells outside expectation for LG/HG per event  
5306   std::vector<TH2D*> h2DTotLGROvsLGHGCheck(setup->GetNMaxROUnit()+1);  // total LG vs LG/HG outside expectation  (with value)
5307   std::vector<TH2D*> h2DTotLGROvsLGHGCheckNCells(setup->GetNMaxROUnit()+1);  // total LG vs LG/HG outside expectation Number of cells
5308   
5309   // HGCROC only
5310   TH2D* hspectraTotvsCellID         = nullptr;      // all cells raw TOT vs cell ID
5311   TH2D* hspectraTotvsCellIDNoise    = nullptr;      // noise trigger flagged raw TOT vs cell ID
5312   TH1D* hSaturatedTOTCellID         = nullptr;      // saturated TOT (HGCROC) frequency vs cell ID
5313   TH1D* hSaturatedTOT               = nullptr;      // saturated TOT (HGCROC) frequency per event
5314   TH2D* hspectraTOAvsCellID         = nullptr;      // raw TOA vs cell ID
5315   TH2D* hSampleTOAVsCellID          = nullptr;      // nSample TOA vs cell ID
5316   TH1D* hSampleTOA                  = nullptr;      // nSample TOA all cells
5317   TH2D* hTOANsVsCellID              = nullptr;      // linearized TOA (ns) vs cellID
5318   TH2D* hTOACorrNsVsCellID          = nullptr;      // corrected linearized TOA (ns) vs cellID
5319   std::vector<std::array<TH2D*, 2>> h2DToAvsnSample(setup->GetNMaxROUnit()+1);           // ToA vs nSample TOA per readout unit half
5320   std::vector<std::array<TH2D*, 2>> h2DWaveFormHalfAsicAll(setup->GetNMaxROUnit()+1);    // ToA corrected Waveform per readout unit half
5321   std::vector<std::array<TProfile*, 2>> hWaveFormHalfAsicAll(setup->GetNMaxROUnit()+1);  // profile of ToA corrected Waveform per readout unit half
5322   
5323   //Create 1D Histos for Delta time
5324   TH1D* hDeltaTime = new TH1D("hDeltaTime", "Time Difference between Events; Delta Time (#mus); Counts", 2000, 0, 100000);
5325   hDeltaTime->SetDirectory(0);
5326   
5327   // create HG and LG histo's per channel
5328   if (typeRO == ReadOut::Type::Caen) {
5329     hspectraHGvsCellID               = new TH2D( "hspectraHG_vsCellID","ADC spectrum High Gain vs CellID; cell ID; ADC_{HG} (arb. units)   ; counts ",
5330                                                 setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5, 4000,0,4000);
5331     hspectraHGvsCellID->SetDirectory(0);
5332     hSaturatedADCvsCellID            = new TH1D( "hSaturatedHGvsCellID","ADC High Gain saturated CellID; cell ID; counts ",
5333                                                 setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5);
5334     hSaturatedADCvsCellID->SetDirectory(0);
5335     hSaturatedADC                    = new TH1D( "hSaturatedADC","ADC High Gain saturated per event; #cells; counts ",
5336                                                 setup->GetNActiveCells()+1, -0.5, setup->GetNActiveCells()+1-0.5);
5337     hSaturatedADC->SetDirectory(0);
5338     hspectraHGCorrvsCellID           = new TH2D( "hspectraHGCorr_vsCellID","ADC spectrum High Gain corrected vs CellID; cell ID; ADC_{HG} (arb. units)  ; counts ",
5339                                                 setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5, 4000,-200,3800);
5340     hspectraHGCorrvsCellID->SetDirectory(0);
5341     hspectraHGCorrvsCellIDNoise      = new TH2D( "hspectraHGCorr_vsCellID_Noise","ADC spectrum High Gain corrected vs CellID Noise; cell ID; ADC_{HG} (arb. units)  ; counts ",
5342                                                 setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5, 4000,-200,3800);
5343     hspectraHGCorrvsCellIDNoise->SetDirectory(0);
5344     hspectraLGvsCellID               = new TH2D( "hspectraLG_vsCellID","ADC spectrum Low Gain vs CellID; cell ID; ADC_{LG} (arb. units)  ; counts",
5345                                                 setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5, 4000,0,4000);
5346     hspectraLGvsCellID->SetDirectory(0);
5347     hspectraLGCorrvsCellID           = new TH2D( "hspectraLGCorr_vsCellID","ADC spectrum Low Gain corrected vs CellID; cell ID; ADC_{LG} (arb. units)  ; counts  ",
5348                                                 setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5, 4000,-200,3800);
5349     hspectraLGCorrvsCellID->SetDirectory(0);
5350     hspectraLGCorrvsCellIDNoise      = new TH2D( "hspectraLGCorr_vsCellID_Noise","ADC spectrum Low Gain corrected vs CellID Noise; cell ID; ADC_{LG} (arb. units)  ; counts  ",
5351                                                 setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5, 4000,-200,3800);
5352     hspectraLGCorrvsCellIDNoise->SetDirectory(0);
5353     hSaturatedLGvsCellID            = new TH1D( "hSaturatedLGvsCellID","ADC spectrum Low Gain saturated CellID; cell ID; counts ",
5354                                                 setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5);
5355     hSaturatedLGvsCellID->SetDirectory(0);
5356     hSaturatedLG                    = new TH1D( "hSaturatedLG","ADC Low Gain saturated per event; #cells; counts ",
5357                                                 setup->GetNActiveCells()+1, -0.5, setup->GetNActiveCells()+1-0.5);
5358     hSaturatedLG->SetDirectory(0);
5359     hLGHGCorrOutsideBoundCellID     = new TH1D( "hLGHGCorrOutsideBoundCellID","LG/HG outside limits CellID; cell ID; counts ",
5360                                                 setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5);
5361     hLGHGCorrOutsideBoundCellID->SetDirectory(0);
5362     hNCellsLGHGCorrOutsideBound     = new TH1D( "hNCellsLGHGCorrOutsideBound","LG/HG outside limits per event; #cells; counts ",
5363                                                 setup->GetNActiveCells()+1, -0.5, setup->GetNActiveCells()+1-0.5);
5364     hNCellsLGHGCorrOutsideBound->SetDirectory(0);
5365     for (Int_t ro = 0; ro < setup->GetNMaxROUnit()+1; ro++){
5366         h2DTotLGROvsLGHGCheck[ro]    = new TH2D(Form("h2DTotLGROvsLGHGCheck_CAENRO_%d",ro),
5367                                               Form("#Sigma LG vs (HG/LG_{HG equiv}-1) CAEN RO: %d ; #Sigma LG RO %d; HG/LG_{HG equiv}-1",ro, ro), 50000/10,-0.5,50000,200,-0.5,1.5);
5368         h2DTotLGROvsLGHGCheck[ro]->SetDirectory(0);
5369         h2DTotLGROvsLGHGCheckNCells[ro]    = new TH2D(Form("h2DTotLGROvsLGHGCheckNCells_CAENRO_%d",ro),
5370                                               Form("#Sigma LG vs (HG/LG_{HG equiv}-1) CAEN RO: %d ; #Sigma LG RO %d; #NCells",ro, ro), 50000/10,-0.5,50000,200,-0.5,1.5);
5371         h2DTotLGROvsLGHGCheckNCells[ro]->SetDirectory(0);
5372     }
5373   } else if (typeRO == ReadOut::Type::Hgcroc) {
5374     hspectraHGvsCellID               = new TH2D( "hspectraHG_vsCellID","ADC spectrum vs CellID; cell ID; ADC (arb. units); counts ",
5375                                                 setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5, 1100,-40.5,1100-40.5);
5376     hspectraHGvsCellID->SetDirectory(0);
5377     hSaturatedADCvsCellID            = new TH1D( "hSaturatedADCvsCellID","ADC saturated CellID; cell ID; counts ",
5378                                                 setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5);
5379     hSaturatedADCvsCellID->SetDirectory(0);
5380     hSaturatedADC                    = new TH1D( "hSaturatedADC","ADC saturated per event; #cells; counts ",
5381                                                 setup->GetNActiveCells()+1, -0.5, setup->GetNActiveCells()+1-0.5);
5382     hSaturatedADC->SetDirectory(0);    
5383     hspectraHGCorrvsCellIDNoise      = new TH2D( "hspectraHGCorr_vsCellID_Noise","ADC spectrum vs CellID Noise; cell ID; ADC (arb. units); counts ",
5384                                                 setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5, 400,-40.5,400-40.5);
5385     hspectraHGCorrvsCellIDNoise->SetDirectory(0);
5386     hspectraTotvsCellID              = new TH2D( "hspectraTot_vsCellID","Tot vs CellID; cell ID; Tot (arb. units); counts  ",
5387                                                 setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5, 4096,0,4096);
5388     hspectraTotvsCellID->SetDirectory(0);
5389     hspectraTotvsCellIDNoise      = new TH2D( "hspectraTot_vsCellID_Noise","Tot vs CellID Noise; cell ID; Tot (arb. units); counts  ",
5390                                                 setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5, 4096,0,4096);
5391     hspectraTotvsCellIDNoise->SetDirectory(0);
5392     hSaturatedTOTCellID              = new TH1D( "hSaturatedTOTCellID","TOT Saturated CellID; cell ID; Saturated cells  ",
5393                                                 setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5);
5394     hSaturatedTOTCellID->SetDirectory(0);
5395     hSaturatedTOT                    = new TH1D( "hSaturatedTOT","TOT saturated per event; #cells; counts ",
5396                                                 setup->GetNActiveCells()+1, -0.5, setup->GetNActiveCells()+1-0.5);
5397     hSaturatedTOT->SetDirectory(0);    
5398     
5399     hspectraTOAvsCellID      = new TH2D( "hspectraTOAvsCellID","TOA spectrums CellID; cell ID; TOA (arb. units) ",
5400                                             setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5, 1024,0,1024);
5401     hspectraTOAvsCellID->SetDirectory(0);
5402     hSampleTOAVsCellID       = new TH2D( "hSampleTOAvsCellID","#sample ToA; cell ID; #sample TOA",
5403                                             setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5, it->second.samples,0,it->second.samples);
5404     hSampleTOAVsCellID->SetDirectory(0);
5405     hSampleTOA                = new TH1D( "hSampleTOA","#sample ToA; #sample TOA",
5406                                               it->second.samples,0,it->second.samples);
5407     hSampleTOA->SetDirectory(0);  
5408     hTOANsVsCellID            = new TH2D( "hTOANsVsCellID","ToA (ns); cell ID; ToA (ns)",
5409                                       setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5, 500,-250,0);
5410     hTOANsVsCellID->SetDirectory(0);
5411     hTOACorrNsVsCellID        = new TH2D( "hTOACorrNsVsCellID","ToA (ns); cell ID; ToA (ns)",
5412                                       setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5, 500,-250,0);
5413     hTOACorrNsVsCellID->SetDirectory(0);
5414     for (Int_t ro = 0; ro < setup->GetNMaxROUnit()+1; ro++){
5415       for (int h = 0; h< 2; h++){
5416         h2DToAvsnSample[ro][h]    = new TH2D(Form("h2DTOASample_Asic_%d_Half_%d",ro,h),
5417                                               Form("Sample vs TOA %d %d; TOA (arb. units); #sample",ro,h), 1024/8,0,1024,it->second.samples,0,it->second.samples);
5418         h2DToAvsnSample[ro][h]->SetDirectory(0);
5419         hWaveFormHalfAsicAll[ro][h]    = new TProfile(Form("WaveForm_Asic_%d_Half_%d",ro,h),
5420                                           Form("ADC-TOA correlation %d %d;  t (ns) ; ADC (arb. units)",ro,h),550,-50,500);
5421         hWaveFormHalfAsicAll[ro][h]->SetDirectory(0);
5422         h2DWaveFormHalfAsicAll[ro][h]  = new TH2D(Form("h2DWaveForm_Asic_%d_Half_%d",ro,h),
5423                                           Form("2D ADC vs TOA %d %d;  t (ns) ; ADC (arb. units)",ro,h), 
5424                                             550,-50,500, 1044/4, -20, 1024);      
5425         h2DWaveFormHalfAsicAll[ro][h]->SetDirectory(0);
5426       }
5427     }
5428   }
5429   // Calibrated energy for cell
5430   TH2D* hspectraEnergyvsCellID  = new TH2D( "hspectraEnergy_vsCellID","Energy vs CellID; cell ID; E (mip eq./tile); counts",
5431                                             setup->GetMaxCellID()+1, -0.5, setup->GetMaxCellID()+1-0.5, 6000,0,200);
5432   hspectraEnergyvsCellID->SetDirectory(0);
5433   // Summed energy in event vs number of active cells
5434   TH2D* hspectraEnergyTotvsNCells  = new TH2D( "hspectraTotEnergy_vsNCells","Energy vs CellID; N_{Cells}; E_{tot} (mip eq./tile); counts",
5435                                             setup->GetNActiveCells()+1, -0.5, setup->GetNActiveCells()+1-0.5, 6000,0,1000);
5436   hspectraEnergyTotvsNCells->SetDirectory(0);
5437   // Summed energy in event vs number of active cells not noise flagged
5438   TH2D* hspectraEnergyTotvsNCellsNoNoise  = new TH2D( "hspectraTotEnergy_vsNCells_NoNoise","Energy vs CellID; N_{Cells}; E_{tot} (mip eq./tile); counts",
5439                                             setup->GetNActiveCells()+1, -0.5, setup->GetNActiveCells()+1-0.5, 6000,0,1000);
5440   hspectraEnergyTotvsNCellsNoNoise->SetDirectory(0);
5441   // Summed energy in event vs number of active cells with cell above mip threshold
5442   TH2D* hspectraEnergyTotvsNCellsST  = new TH2D( "hspectraTotEnergy_vsNCellsST","Energy vs CellID; N_{Tiles}; E_{tot} (mip eq./tile); counts",
5443                                             (setup->GetNActiveCells()*5)+1, -0.5, (setup->GetNActiveCells()*10)+1-0.5, 6000,0,1000);
5444   hspectraEnergyTotvsNCellsST->SetDirectory(0);
5445   
5446   std::map<int,TileSpectra> hSpectra;
5447   std::map<int, TileSpectra>::iterator ithSpectra;
5448   std::map<int,TileSpectra> hSpectraLocalTrigg;
5449   std::map<int, TileSpectra>::iterator ithSpectraLocalTrigg;
5450   std::map<int,TileSpectra> hSpectraNoise;
5451   std::map<int, TileSpectra>::iterator ithSpectraNoise;
5452   std::map<int,TileSpectra> hSpectraNotNoise;
5453   std::map<int, TileSpectra>::iterator ithSpectraNotNoise;
5454   
5455   // entering histoOutput file
5456   RootOutputHist->mkdir("IndividualCells");
5457   RootOutputHist->cd("IndividualCells");
5458   RootOutputHist->mkdir("IndividualCellsNoise");
5459   RootOutputHist->cd("IndividualCellsNoise");
5460   RootOutputHist->mkdir("IndividualCellsLocalTrigg");
5461   RootOutputHist->cd("IndividualCellsLocalTrigg");
5462 
5463   RootOutput->cd();
5464   
5465   //=============================================================================================
5466   // Setup general variables for analysis
5467   //=============================================================================================
5468   int actCh1st                = 0;
5469   double averageScale         = calib.GetAverageScaleHigh(actCh1st);
5470   int actChalt                = 0;
5471   double averageNTiles        = 0.;
5472   double averageScalePerTile  = calib.GetAverageScaleHighPerSingleLayer(actChalt, averageNTiles);
5473   // variable per single tile for possible summed output
5474   double avLGHGCorr           = calib.GetAverageLGHGCorr();
5475   double avLGHGCorrOff        = calib.GetAverageLGHGCorrOff();
5476   
5477   int actCh1stL                = 0;
5478   double averageScaleL        = 0;
5479   int actChaltL               = 0;
5480   double averageNTilesL       = 0.;
5481   double averageLScalePerTile = 0.;
5482   if (typeRO == ReadOut::Type::Caen){
5483     averageScaleL        = calib.GetAverageScaleLow(actCh1stL);
5484     averageLScalePerTile = calib.GetAverageScaleLowPerSingleLayer(actChaltL, averageNTilesL);
5485   }
5486   // print out key calib variables
5487   if (typeRO == ReadOut::Type::Caen){
5488     std::cout << "average HG mip: " << averageScale << "\t per tile: " << averageScalePerTile<< "\t active ch: "<< actCh1st<< std::endl;
5489     std::cout << "average LG mip: " << averageScaleL <<"\t per tile: " << averageLScalePerTile<< "\t active ch: "<< actCh1stL<< std::endl;
5490   } else if (typeRO == ReadOut::Type::Hgcroc){
5491     std::cout << "average HG mip: " << averageScale << "\t per tile: " << averageScalePerTile << "\t active ch: "<< actCh1st<< "\t average Ntiles for calib: "<< averageNTiles << std::endl;
5492   }
5493   
5494   // Set correct calib scale for trigger eval
5495   double calibScale           = 0;
5496   if (typeRO == ReadOut::Type::Caen ){
5497     // LG scale as evaluated from fits
5498     if (calibOption == 0){
5499       calibScale  = averageLScalePerTile;
5500       std::cout << "Estimating triggers using calib option " << calibOption << ". This uses the average of all LG evaluated fits, averages is: " << calibScale << std::endl;
5501     // LG scale calc from HG
5502     } else if (calibOption == 1){
5503       calibScale  = (averageScalePerTile-avLGHGCorrOff)/avLGHGCorr;
5504       std::cout << "Estimating triggers using calib option " << calibOption << ". This uses the average of all HG evaluated fits and calculates LG equivalent, averages is: " << calibScale << std::endl;
5505     // HG scale as evaluated from fits
5506     } else if (calibOption >= 2){
5507       calibScale  = averageScalePerTile;
5508       std::cout << "Estimating triggers using calib option " << calibOption << ". This uses the average of all HG evaluated fits, averages is: " << calibScale << std::endl;
5509     } else {
5510       std::cout << "This calib option is unknown: " << calibOption << " *************** ABORTING!!!!" << std::endl;
5511       return false;
5512     }
5513   } else {
5514     calibScale  = averageScalePerTile;
5515     std::cout << " Calibrating using average ADC max fits, averages is: " << calibScale << std::endl;
5516   }
5517 
5518   // setup local trigger sel
5519   TRandom3* rand    = new TRandom3();
5520   Int_t localTriggerTiles     = 4;
5521   if (yearData == 2023){
5522     localTriggerTiles         = 6;
5523   }
5524   double factorMinTrigg       = 0.8;
5525   double factorMinTriggNoise  = 0.2;
5526   double factorMaxTrigg       = 2.5;
5527   if (yearData == 2023){
5528     factorMinTrigg            = 0.9;
5529     factorMaxTrigg            = 2.;
5530   }
5531   int corrHGADCSwap           = 3500;
5532   int evts=TdataIn->GetEntries();
5533   if (maxEvents == -1){
5534     maxEvents                 = evts;
5535   } else {
5536     std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
5537     std::cout << "ATTENTION: YOU ARE RESETTING THE MAXIMUM NUMBER OF EVENTS TO BE PROCESSED TO: " << maxEvents << ". THIS SHOULD ONLY BE USED FOR TESTING!" << std::endl;
5538     std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
5539   }
5540   int outCount                = 5000;
5541   if (evts < 10000)
5542     outCount                  = 500;
5543   
5544   int nLocalNoiseTriggs       = 0;
5545   int nLocalMuonTriggs        = 0;
5546   
5547   if (EventCleanup == 1){
5548     std::cout << "==============================================================================" << std::endl;
5549     std::cout << "==============================================================================" << std::endl;
5550     if (calib.GetAverageScaleHigh() != -10000 ){
5551       std::cout << "resetting rejection thresholds with average HG Scale" << std::endl;
5552       cleanupLGTh   =  ((calib.GetAverageScaleHigh()-calib.GetAverageLGHGCorrOff())/calib.GetAverageLGHGCorr() )* 2.5;
5553       cleanupHGTh   =  calib.GetAverageScaleHigh()*1.5;
5554     }
5555     std::cout << "Thresholds for rejections: \t LG: " << cleanupLGTh << "\t HG: " << cleanupHGTh << std::endl;
5556     std::cout << "==============================================================================" << std::endl;
5557     std::cout << "==============================================================================" << std::endl;
5558   }
5559   int rejectedEvents  = 0;
5560 
5561   double last_time = 0;
5562   double DeltaTime = 1000000000;
5563 
5564   //==================================================================================
5565   // setup waveform builder for HGCROC data
5566   //==================================================================================
5567   waveform_fit_base *waveform_builder = nullptr;
5568   if (GetHGCROCOptInteg() == 1 || GetHGCROCOptInteg() == 101){
5569     waveform_builder = new max_sample_fit_n_integ(GetHGCROCNSampleInteg());
5570   } else {
5571     waveform_builder = new max_sample_fit();
5572   }
5573       
5574   //=============================================================================================
5575   // Run over all events in tree
5576   //=============================================================================================
5577   for(int i=0; i<evts && i < maxEvents; i++){
5578     if(debug==1000){
5579         std::cerr<<event.GetTimeStamp()<<std::endl;
5580       }
5581     TdataIn->GetEntry(i);
5582     if (i%outCount == 0 && debug > 0) std::cout << "Reading " <<  i << " / " << evts << " events" << std::endl;
5583     
5584     bool bREvent = false;
5585     if (EventCleanup == 1){
5586       if (!event.CheckEventIntegrity(calib, cleanupLGTh, cleanupHGTh)){
5587         rejectedEvents++;
5588         bREvent = true;
5589         continue;
5590       }
5591     }
5592 
5593     // check delta timing
5594     // Find and fill delta time
5595     double current_time = event.GetTimeStamp();
5596     if(last_time != 0){
5597       DeltaTime = current_time - last_time;
5598       if (debug == 1000){
5599         std::cerr<< "current timestamp: "<< current_time<<std::endl;
5600       }
5601     }
5602     if (DeltaTime == 0){
5603       if(debug == 1001){
5604         std::cerr<< "Run Number: " << runNr <<"      Event Number: "<< i << std::endl;
5605         std::cerr<< "Previous Timestamp (us): "<< last_time <<"      Current Timestamp: "<< current_time<<std::endl;
5606       }
5607     }
5608     // Provisioning for cut based on DeltaTime range
5609     // if(DeltaTime < timemin || DeltaTime > timemax){
5610     //   //std::cout<<"event rejected:"<< i <<std::endl;
5611     //   last_time = current_time;
5612     //   continue;
5613     // }
5614     hDeltaTime->Fill(DeltaTime);
5615     last_time = current_time;
5616 
5617     
5618     // event based counters and sums
5619     double Etot         = 0;    // total energy in event
5620     int nCells          = 0;    // NCells in event
5621     int nCellsST        = 0;    // Ncells single tile equivalent
5622     double EtotNoNoise  = 0;    // total enegy without noise flagged cells
5623     int nCellsNoNoise   = 0;    // Ncells without noise flagged cells
5624     int satCellsADC     = 0;    // number of cells saturating ADC (HG - CAEN, ADC - HGCROC)
5625     int satCellsTOT     = 0;    // number of cells saturating TOT (HGCROC)
5626     int satCellsADCLG   = 0;    // number of cells saturating LG ADC (CAEN)
5627     int lghgFailCells   = 0;    // number of cells incongruent with expected LG-HG correlation (CAEN)
5628     //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5629     // Single tile processing 
5630     //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5631     for(int j=0; j<event.GetNTiles(); j++){
5632       // tile energy
5633       double energy = 0;      
5634       // calculate trigger primitives
5635       bool localMuonTrigg   = false;
5636       bool localNoiseTrigg  = false;
5637 
5638       //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5639       // CAEN treatment
5640       //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5641       if (typeRO == ReadOut::Type::Caen) {
5642         Caen* aTile=(Caen*)event.GetTile(j);
5643         // remove bad channels from output
5644         if (calib.GetBCCalib() && calib.GetBadChannel(aTile->GetCellID())!= 3 ){
5645           event.RemoveTile(aTile);
5646           j--;        
5647           continue;
5648         }
5649         
5650         // --------------------------------------------------------------------------------------------------------------
5651         // calculate corrected variables
5652         // --------------------------------------------------------------------------------------------------------------
5653         double corrHG = aTile->GetADCHigh()-calib.GetPedestalMeanH(aTile->GetCellID());
5654         double corrLG = aTile->GetADCLow()-calib.GetPedestalMeanL(aTile->GetCellID());
5655         double corrLG_HGeq = corrLG*calib.GetLGHGCorr(aTile->GetCellID()) + calib.GetLGHGCorrOff(aTile->GetCellID());
5656         
5657         // --------------------------------------------------------------------------------------------------------------
5658         // check whehter HG or LG saturated
5659         // --------------------------------------------------------------------------------------------------------------
5660         if(aTile->IsSaturatedADCHigh()){
5661           satCellsADC++;
5662           hSaturatedADCvsCellID->Fill(aTile->GetCellID());
5663         }
5664         if(aTile->IsSaturatedADCLow()){
5665           satCellsADCLG++;
5666           hSaturatedLGvsCellID->Fill(aTile->GetCellID());
5667         }
5668         // check if lg - hg correlation falls within acceptable bounds
5669         bool lghgRatioAcceptable    = false;
5670         double lghgRatio            = (corrHG/corrLG_HGeq) - 1;
5671         if (TMath::Abs(lghgRatio) < 0.3)
5672           lghgRatioAcceptable       = true;
5673         bool isHGSatAndLGAcceptable = false;
5674         if (aTile->IsSaturatedADCHigh()){
5675           // has LG has to be at least in acceptable region
5676           if (corrLG > 3500/calib.GetLGHGCorr(aTile->GetCellID())){
5677             isHGSatAndLGAcceptable  = true;
5678             lghgRatioAcceptable     = true;
5679           }
5680         }
5681           
5682         if (!lghgRatioAcceptable && corrLG > 10*calib.GetPedestalSigL(aTile->GetCellID())){
5683           lghgFailCells++;
5684           hLGHGCorrOutsideBoundCellID->Fill(aTile->GetCellID());
5685         }
5686 
5687         // --------------------------------------------------------------------------------------------------------------
5688         // Switching for calibration options
5689         // --------------------------------------------------------------------------------------------------------------
5690         // Using LG only with mip scale from HG scaled to LG 
5691         // --------------------------------------------------------------------------------------------------------------  
5692         if (calibOption == 0){
5693           if(corrLG/calib.GetScaleLow(aTile->GetCellID()) > minMipFrac)
5694             energy=corrLG/calib.GetScaleLow(aTile->GetCellID());
5695         // --------------------------------------------------------------------------------------------------------------
5696         // Using LG only with mip scale from HG scaled to LG 
5697         // --------------------------------------------------------------------------------------------------------------  
5698         } else if (calibOption == 1){
5699           if(corrLG/calib.GetCalcScaleLowAlter(aTile->GetCellID()) > minMipFrac) 
5700             energy=corrLG/calib.GetCalcScaleLowAlter(aTile->GetCellID());
5701         // --------------------------------------------------------------------------------------------------------------  
5702         // Stiching signal from HG and LG, using respective mip fits for calibration
5703         // --------------------------------------------------------------------------------------------------------------
5704         } else if (calibOption == 2){
5705           if(corrHG<corrHGADCSwap){
5706             if(corrHG/calib.GetScaleHigh(aTile->GetCellID()) > minMipFrac){
5707               energy=corrHG/calib.GetScaleHigh(aTile->GetCellID());
5708             }
5709           } else {
5710             energy=corrLG/calib.GetScaleLow(aTile->GetCellID());
5711           }          
5712           if (debug > 1 && corrHG >= corrHGADCSwap-100 && corrHG < 4000-calib.GetPedestalMeanH(aTile->GetCellID())){
5713               std::cout << "-> Cell ID: " <<  aTile->GetCellID() << "\t HG\t" << corrHG << "\t" << corrHG/calib.GetScaleHigh(aTile->GetCellID()) << "\t LG \t" << corrLG << "\t" <<  corrLG/calib.GetCalcScaleLow(aTile->GetCellID()) << "\t"<< corrLG/calib.GetScaleLow(aTile->GetCellID()) << "\t delta: \t"<< corrHG/calib.GetScaleHigh(aTile->GetCellID())-(corrLG/calib.GetCalcScaleLow(aTile->GetCellID())) << "\tLGHG\t" << calib.GetLGHGCorr(aTile->GetCellID())<< std::endl;
5714           }
5715         // --------------------------------------------------------------------------------------------------------------
5716         // Stiching signal from HG and LG, using respective HG mip fits for calibration & scaled LG
5717         // --------------------------------------------------------------------------------------------------------------
5718         } else if (calibOption == 3){
5719           if(corrHG<corrHGADCSwap){
5720             if(corrHG/calib.GetScaleHigh(aTile->GetCellID()) > minMipFrac){
5721               energy=corrHG/calib.GetScaleHigh(aTile->GetCellID());
5722             }
5723           } else {
5724             // use calculation with offset for LG Scale calculation
5725             energy=corrLG/calib.GetCalcScaleLowAlter(aTile->GetCellID());
5726           } 
5727         }
5728         // --------------------------------------------------------------------------------------------------------------
5729         // check if you need to rerun the trigger
5730         // --------------------------------------------------------------------------------------------------------------
5731         if (!UseLocTriggFromFile()){
5732           // running triggers evaluation
5733           aTile->SetLocalTriggerPrimitive(event.CalculateLocalMuonTrigg(calib, rand, aTile->GetCellID(), localTriggerTiles, avLGHGCorr, calibOption));
5734           aTile->SetLocalTriggerBit(0);
5735           localMuonTrigg   = event.InspectIfLocalMuonTrigg(aTile->GetCellID(), calibScale, factorMinTrigg, factorMaxTrigg);
5736           localNoiseTrigg  = event.InspectIfNoiseTrigg(aTile->GetCellID(), calibScale, factorMinTriggNoise);
5737           if (localMuonTrigg) aTile->SetLocalTriggerBit(1);
5738           if (localNoiseTrigg) aTile->SetLocalTriggerBit(2);
5739         // --------------------------------------------------------------------------------------------------------------            ;
5740         // trigger decision taken from input file
5741         // --------------------------------------------------------------------------------------------------------------
5742         } else {
5743           if (aTile->GetLocalTriggerBit() == 2)  localNoiseTrigg  = true;
5744           // reeval muon trigger based on updated values
5745           localMuonTrigg  = event.InspectIfLocalMuonTrigg(aTile->GetCellID(), calibScale, factorMinTrigg, factorMaxTrigg);
5746           if (localMuonTrigg) aTile->SetLocalTriggerBit(1);
5747         }
5748         
5749         // --------------------------------------------------------------------------------------------------------------
5750         // filling QA histograms
5751         // --------------------------------------------------------------------------------------------------------------
5752         hspectraHGvsCellID->Fill(aTile->GetCellID(), aTile->GetADCHigh());
5753         hspectraLGvsCellID->Fill(aTile->GetCellID(), aTile->GetADCLow());
5754         hspectraHGCorrvsCellID->Fill(aTile->GetCellID(), corrHG);
5755         hspectraLGCorrvsCellID->Fill(aTile->GetCellID(), corrLG);
5756         
5757         if (localNoiseTrigg){
5758           hspectraHGCorrvsCellIDNoise->Fill(aTile->GetCellID(), corrHG);
5759           hspectraLGCorrvsCellIDNoise->Fill(aTile->GetCellID(), corrLG);        
5760         }
5761         // --------------------------------------------------------------------------------------------------------------
5762         // spectra (all cells)
5763         // --------------------------------------------------------------------------------------------------------------
5764         ithSpectra=hSpectra.find(aTile->GetCellID());
5765         if(ithSpectra!=hSpectra.end()){
5766           ithSpectra->second.FillExtCAEN(corrLG,corrHG,energy,corrLG_HGeq);
5767         } else {
5768           RootOutputHist->cd("IndividualCells");
5769           hSpectra[aTile->GetCellID()]=TileSpectra("Calibrate",1,aTile->GetCellID(),calib.GetTileCalib(aTile->GetCellID()),event.GetROtype(), nSampleHGCROCInt, debug);
5770           hSpectra[aTile->GetCellID()].FillExtCAEN(corrLG,corrHG,energy,corrLG_HGeq);
5771           RootOutput->cd();
5772         }
5773 
5774         // --------------------------------------------------------------------------------------------------------------
5775         // spectra for local muon triggers
5776         // --------------------------------------------------------------------------------------------------------------
5777         if (localMuonTrigg){
5778           nLocalMuonTriggs++;
5779           ithSpectraLocalTrigg=hSpectraLocalTrigg.find(aTile->GetCellID());
5780           if(ithSpectraLocalTrigg!=hSpectraLocalTrigg.end()){
5781             ithSpectraLocalTrigg->second.FillExtCAEN(corrLG,corrHG,energy,corrLG_HGeq);
5782           } else {
5783             RootOutputHist->cd("IndividualCellsLocalTrigg");
5784             hSpectraLocalTrigg[aTile->GetCellID()]=TileSpectra("CalibrateLocalTrigg",1,aTile->GetCellID(),calib.GetTileCalib(aTile->GetCellID()),event.GetROtype(), nSampleHGCROCInt, debug);
5785             hSpectraLocalTrigg[aTile->GetCellID()].FillExtCAEN(corrLG,corrHG,energy,corrLG_HGeq);
5786             RootOutput->cd();
5787           }
5788         }
5789         // --------------------------------------------------------------------------------------------------------------
5790         // spectra for local noise triggers
5791         // --------------------------------------------------------------------------------------------------------------
5792         if (localNoiseTrigg){
5793           nLocalNoiseTriggs++;
5794           ithSpectraNoise=hSpectraNoise.find(aTile->GetCellID());
5795           if(ithSpectraNoise!=hSpectraNoise.end()){
5796             ithSpectraNoise->second.FillExtCAEN(corrLG,corrHG,energy,corrLG_HGeq);
5797           } else {
5798             RootOutputHist->cd("IndividualCellsNoise");
5799             hSpectraNoise[aTile->GetCellID()]=TileSpectra("CalibrateNoise",1,aTile->GetCellID(),calib.GetTileCalib(aTile->GetCellID()),event.GetROtype(), nSampleHGCROCInt, debug);
5800             hSpectraNoise[aTile->GetCellID()].FillExtCAEN(corrLG,corrHG,energy,corrLG_HGeq);
5801             RootOutput->cd();
5802           }
5803         // --------------------------------------------------------------------------------------------------------------
5804         // spectra for not local noise triggers
5805         // --------------------------------------------------------------------------------------------------------------
5806         } else {
5807           ithSpectraNotNoise=hSpectraNotNoise.find(aTile->GetCellID());
5808           if(ithSpectraNotNoise!=hSpectraNotNoise.end()){
5809             ithSpectraNotNoise->second.FillExtCAEN(corrLG,corrHG,energy,corrLG_HGeq);
5810           } else {
5811             RootOutputHist->cd("IndividualCellsNoise");
5812             hSpectraNotNoise[aTile->GetCellID()]=TileSpectra("CalibrateNotNoise",1,aTile->GetCellID(),calib.GetTileCalib(aTile->GetCellID()),event.GetROtype(), nSampleHGCROCInt, debug);
5813             hSpectraNotNoise[aTile->GetCellID()].FillExtCAEN(corrLG,corrHG,energy,corrLG_HGeq);
5814             RootOutput->cd();
5815           }          
5816         }
5817         // --------------------------------------------------------------------------------------------------------------
5818         // how many cells do I have not tagged as pure noise?
5819         // --------------------------------------------------------------------------------------------------------------
5820         if (!localNoiseTrigg){
5821           EtotNoNoise  = EtotNoNoise+energy; 
5822           nCellsNoNoise++;
5823         }
5824         // --------------------------------------------------------------------------------------------------------------
5825         // reject cell if not above minimum threshold
5826         // --------------------------------------------------------------------------------------------------------------
5827         if(energy > minMipFrac){ 
5828           aTile->SetE(energy);
5829           hspectraEnergyvsCellID->Fill(aTile->GetCellID(), energy);
5830           Etot=Etot+energy;
5831           nCells++;
5832         // --------------------------------------------------------------------------------------------------------------
5833         // delete tile if pure noise, cleanup
5834         // --------------------------------------------------------------------------------------------------------------
5835         } else {
5836           event.RemoveTile(aTile);
5837           j--;
5838         }
5839         
5840       //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5841       // HGCROC treatment
5842       //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5843       } else if (typeRO == ReadOut::Type::Hgcroc){
5844         Hgcroc* aTile=(Hgcroc*)event.GetTile(j);
5845         // remove bad channels from output
5846         if (calib.GetBCCalib() && calib.GetBadChannel(aTile->GetCellID())!= 3 ){
5847           event.RemoveTile(aTile);
5848           j--;        
5849           continue;
5850         }
5851         
5852         // get pedestal values from calib object
5853         double ped = calib.GetPedestalMeanL(aTile->GetCellID()); // ped based on waveform fit
5854         if (ped == -1000){
5855           ped = calib.GetPedestalMeanH(aTile->GetCellID());      // ped based on first sample fit
5856           if (ped == -1000){
5857             ped = aTile->GetPedestal();              // event-by-event first sample
5858           }
5859         }
5860         // reevaluate waveform
5861         waveform_builder->set_waveform(aTile->GetADCWaveform());
5862         waveform_builder->fit_with_average_ped(ped);
5863         aTile->SetIntegratedADC(waveform_builder->get_E());
5864         aTile->SetPedestal(waveform_builder->get_pedestal());
5865 
5866         double adc = aTile->GetIntegratedADC();
5867         double tot = aTile->GetRawTOT();
5868         double toa = aTile->GetRawTOA();
5869         bool hasTOA     = false;
5870         bool hasTOT     = false;
5871         
5872         // check if we have a toa
5873         if (toa > 0)
5874           hasTOA        = true;
5875         // check if we have a tot
5876         if (tot > 0)
5877           hasTOT        = true;
5878         // obtain toa shift corrected values
5879         Int_t nSampTOA  = aTile->GetFirstTOASample();        
5880         double toaNs      = (double)aTile->GetLinearizedRawTOA()*aTile->GetTOATimeResolution();
5881         double toaCorrNs  = toaNs;
5882         Int_t nOffEmpty   = 2;
5883         if (calib.GetToAOff(aTile->GetCellID()) != -1000.){
5884           // correct ToA sample and return correct nSampleTOA
5885           nSampTOA      = aTile->SetCorrectedTOA(calib.GetToAOff(aTile->GetCellID())); 
5886           toaCorrNs     = (double)(aTile->GetCorrectedTOA())*aTile->GetTOATimeResolution();;
5887         }
5888 
5889         // temporarily only calibrate with adc & average Scale
5890         // double tempE = adc/averageScale; 
5891         double energy      = adc/(calib.GetScaleHighPerSingleLayer(aTile->GetCellID()) );
5892         double energySeg  = adc/(calib.GetScaleHigh(aTile->GetCellID()) );
5893 
5894         if (debug > 1 && adc >= 900 ){
5895             std::cout << "----> High ADC Cell ID: " <<  aTile->GetCellID() << "\t ADC\t" << adc << "\t" <<  "\t Tot \t" << tot << "\t toa\t"  <<  toa<< std::endl;
5896         }
5897         if (debug > 1 && tot >= 0 ){
5898             std::cout << "----> Tot fired Cell ID: " <<  aTile->GetCellID() << "\t ADC\t" << adc << "\t" <<  "\t Tot \t" << tot << "\t toa\t"  <<  toa<< std::endl;
5899         }
5900         // calculate local trigger primitives
5901         if (!UseLocTriggFromFile()){
5902           aTile->SetLocalTriggerPrimitive(event.CalculateLocalMuonTrigg(calib, rand, aTile->GetCellID(), localTriggerTiles, 0., 0));
5903           aTile->SetLocalTriggerBit(0);
5904           localMuonTrigg   = event.InspectIfLocalMuonTrigg(aTile->GetCellID(), calibScale, factorMinTrigg, factorMaxTrigg);
5905           localNoiseTrigg  = event.InspectIfNoiseTrigg(aTile->GetCellID(), calibScale, factorMinTriggNoise);
5906           if (localMuonTrigg) aTile->SetLocalTriggerBit(1);
5907           if (localNoiseTrigg) aTile->SetLocalTriggerBit(2);
5908         // trigger decision taken from inout file
5909         } else {
5910           if (aTile->GetLocalTriggerBit() == 2)  localNoiseTrigg  = true;
5911           // reeval muon trigger based on updated values
5912           localMuonTrigg  = event.InspectIfLocalMuonTrigg(aTile->GetCellID(), calibScale, factorMinTrigg, factorMaxTrigg);
5913           if (localMuonTrigg) aTile->SetLocalTriggerBit(1);
5914         }
5915         
5916         hspectraHGvsCellID->Fill(aTile->GetCellID(), adc);
5917         if(hasTOT)  hspectraTotvsCellID->Fill(aTile->GetCellID(), tot);
5918         if(aTile->IsSaturatedADC()){
5919           satCellsADC++;
5920           hSaturatedTOTCellID->Fill(aTile->GetCellID());
5921         }
5922         if(aTile->IsSaturatedTOT()){
5923           satCellsTOT++;
5924           hSaturatedTOTCellID->Fill(aTile->GetCellID());
5925         }
5926         if (localNoiseTrigg){
5927           hspectraHGCorrvsCellIDNoise->Fill(aTile->GetCellID(), adc);
5928           if(hasTOT) hspectraTotvsCellIDNoise->Fill(aTile->GetCellID(), tot);        
5929         }
5930         
5931         Int_t asic      = setup->GetROunit(aTile->GetCellID());
5932         Int_t roCh      = setup->GetROchannel(aTile->GetCellID());
5933         if (hasTOA){
5934           hspectraTOAvsCellID->Fill(aTile->GetCellID(),toa);
5935           hSampleTOAVsCellID->Fill(aTile->GetCellID(),nSampTOA);
5936           hSampleTOA->Fill(nSampTOA);
5937           hTOANsVsCellID->Fill(aTile->GetCellID(),toaNs);
5938           hTOACorrNsVsCellID->Fill(aTile->GetCellID(),toaCorrNs);
5939           // fill overview hists for half asics
5940           h2DToAvsnSample[asic][int(roCh/36)]->Fill(toa, nSampTOA);
5941           for (int k = 0; k < (int)(aTile->GetADCWaveform()).size(); k++ ){
5942             double timetemp = ((k+nOffEmpty)*1024 + (double)aTile->GetCorrectedTOA())*aTile->GetTOATimeResolution() ;
5943             hWaveFormHalfAsicAll[asic][int(roCh/36)]->Fill(timetemp,(aTile->GetADCWaveform()).at(k)-ped);
5944             h2DWaveFormHalfAsicAll[asic][int(roCh/36)]->Fill(timetemp,(aTile->GetADCWaveform()).at(k)-ped);
5945           }          
5946         }        
5947 
5948         ithSpectra=hSpectra.find(aTile->GetCellID());
5949         if(ithSpectra!=hSpectra.end()){
5950           ithSpectra->second.FillExtHGCROC(adc,toa,tot,nSampTOA,-1);
5951         } else {
5952           RootOutputHist->cd("IndividualCells");
5953           hSpectra[aTile->GetCellID()]=TileSpectra("Calibrated",2,aTile->GetCellID(),calib.GetTileCalib(aTile->GetCellID()),event.GetROtype(), nSampleHGCROCInt, debug);
5954           hSpectra[aTile->GetCellID()].FillExtHGCROC(adc,toa,tot,nSampTOA,-1);
5955           RootOutput->cd();
5956         }
5957 
5958         if(localMuonTrigg) nLocalMuonTriggs++;
5959         
5960         ithSpectraLocalTrigg=hSpectraLocalTrigg.find(aTile->GetCellID());
5961         if(ithSpectraLocalTrigg!=hSpectraLocalTrigg.end()){
5962           if (localMuonTrigg) ithSpectraLocalTrigg->second.FillHGCROC(adc,toa,tot);
5963           ithSpectraLocalTrigg->second.FillTrigger(aTile->GetLocalTriggerPrimitive());
5964         } else {
5965           RootOutputHist->cd("IndividualCellsLocalTrigg");
5966           hSpectraLocalTrigg[aTile->GetCellID()]=TileSpectra("CalibratedLocalTrigg",aTile->GetCellID(),calib.GetTileCalib(aTile->GetCellID()),event.GetROtype(), nSampleHGCROCInt, debug);
5967           if (localMuonTrigg) hSpectraLocalTrigg[aTile->GetCellID()].FillHGCROC(adc,toa,tot);
5968           hSpectraLocalTrigg[aTile->GetCellID()].FillTrigger(aTile->GetLocalTriggerPrimitive());
5969           RootOutput->cd();
5970         }
5971       
5972         if (localNoiseTrigg){
5973           nLocalNoiseTriggs++;
5974           ithSpectraNoise=hSpectraNoise.find(aTile->GetCellID());
5975           if(ithSpectraNoise!=hSpectraNoise.end()){
5976             ithSpectraNoise->second.FillHGCROC(adc,toa,tot);
5977           } else {
5978             RootOutputHist->cd("IndividualCellsNoise");
5979             hSpectraNoise[aTile->GetCellID()]=TileSpectra("CalibratedNoise",2,aTile->GetCellID(),calib.GetTileCalib(aTile->GetCellID()),event.GetROtype(), nSampleHGCROCInt, debug);
5980             hSpectraNoise[aTile->GetCellID()].FillHGCROC(adc,toa,tot);
5981             RootOutput->cd();
5982           }
5983         } else {
5984           ithSpectraNotNoise=hSpectraNotNoise.find(aTile->GetCellID());
5985           if(ithSpectraNotNoise!=hSpectraNotNoise.end()){
5986             ithSpectraNotNoise->second.FillHGCROC(adc,toa,tot);
5987           } else {
5988             RootOutputHist->cd("IndividualCells");
5989             hSpectraNotNoise[aTile->GetCellID()]=TileSpectra("CalibratedNotNoise",2,aTile->GetCellID(),calib.GetTileCalib(aTile->GetCellID()),event.GetROtype(), nSampleHGCROCInt, debug);
5990             hSpectraNotNoise[aTile->GetCellID()].FillHGCROC(adc,toa,tot);
5991             RootOutput->cd();
5992           }
5993           
5994         }
5995         
5996         if (!localNoiseTrigg){
5997           EtotNoNoise  = EtotNoNoise+energy; 
5998           nCellsNoNoise++;
5999         }
6000         
6001         // only save if energy is larger minMip fraction
6002         if(energySeg > minMipFrac){ 
6003           aTile->SetE(energy);
6004           hspectraEnergyvsCellID->Fill(aTile->GetCellID(), energy);
6005           Etot=Etot+energy;
6006           nCells++;
6007           nCellsST= nCellsST+setup->GetLayersInSegment(aTile->GetCellID());
6008         } else {
6009           event.RemoveTile(aTile);
6010           j--;
6011         }
6012       } 
6013     } // end single tile loop
6014     
6015     hspectraEnergyTotvsNCells->Fill(nCells,Etot);
6016     hspectraEnergyTotvsNCellsNoNoise->Fill(nCellsNoNoise,EtotNoNoise);
6017     hspectraEnergyTotvsNCellsST->Fill(nCellsST,Etot);
6018     
6019     // checks for event integrity
6020     hSaturatedADC->Fill(satCellsADC);
6021     if (typeRO == ReadOut::Type::Caen){
6022       hSaturatedLG->Fill(satCellsADCLG);
6023       hNCellsLGHGCorrOutsideBound->Fill(lghgFailCells);
6024     } else if (typeRO == ReadOut::Type::Hgcroc) {
6025       hSaturatedTOT->Fill(satCellsTOT);
6026     }
6027     
6028     RootOutput->cd();
6029     if (!bREvent) TdataOut->Fill();
6030   }
6031   
6032   if (EventCleanup == 1){
6033     std::cout << "****************************************************************************************************"<< std::endl; 
6034     std::cout << "****************************************************************************************************"<< std::endl; 
6035     std::cout << rejectedEvents<< "\t/" << maxEvents  << " rejected CAEN events due to corrupted data for single channels!"<< std::endl; 
6036     std::cout << "****************************************************************************************************"<< std::endl; 
6037     std::cout << "****************************************************************************************************"<< std::endl; 
6038   }
6039 
6040 
6041   std::cout << "=======================================================" << std::endl;
6042   std::cout << "Total events processed " << maxEvents << std::endl;
6043   std::cout << "Local muon triggered " << nLocalMuonTriggs << std::endl;
6044   std::cout << "Local noise triggered " << nLocalNoiseTriggs << std::endl;
6045   std::cout << "=======================================================" << std::endl;
6046   //*********************************************************************************************
6047   // Write Output tree
6048   //*********************************************************************************************  
6049   TdataOut->Write();
6050   TsetupIn->CloneTree()->Write();
6051   
6052   if (IsCalibSaveToFile()){
6053     TString fileCalibPrint = RootOutputName;
6054     fileCalibPrint         = fileCalibPrint.ReplaceAll(".root","_calib.txt");
6055     calib.PrintCalibToFile(fileCalibPrint);
6056   }
6057   
6058   TcalibOut->Fill();
6059   TcalibOut->Write();
6060   
6061   
6062   RootOutput->Close();
6063   RootInput->Close();      
6064   
6065   //*********************************************************************************************
6066   // Write Output hist File
6067   //*********************************************************************************************
6068   RootOutputHist->cd();
6069 
6070     hDeltaTime->Write();
6071     hspectraHGvsCellID->Write();
6072     hspectraHGCorrvsCellIDNoise->Write();
6073     hSaturatedADC->Write();
6074     hSaturatedADCvsCellID->Write();
6075     if (typeRO == ReadOut::Type::Caen){
6076       hspectraHGCorrvsCellID->Write();
6077       hspectraLGvsCellID->Write();
6078       hspectraLGCorrvsCellID->Write();
6079       hspectraLGCorrvsCellIDNoise->Write();
6080       hSaturatedLG->Write();
6081       hSaturatedLGvsCellID->Write();
6082       hLGHGCorrOutsideBoundCellID->Write();
6083       hNCellsLGHGCorrOutsideBound->Write();
6084     } else {
6085       hspectraTotvsCellID->Write();
6086       hspectraTotvsCellIDNoise->Write();
6087       hSaturatedTOT->Write();
6088       hSaturatedTOTCellID->Write();
6089       hSampleTOA->Write();
6090       hSampleTOAVsCellID->Write();
6091       hTOANsVsCellID->Write();
6092       hTOACorrNsVsCellID->Write();
6093       hspectraTOAvsCellID->Write();
6094       for (Int_t ro = 0; ro < setup->GetNMaxROUnit()+1; ro++){
6095         for (int h = 0; h< 2; h++){
6096           h2DToAvsnSample[ro][h]->Write();
6097           h2DWaveFormHalfAsicAll[ro][h]->Write();
6098           hWaveFormHalfAsicAll[ro][h]->Write();
6099         }
6100       }
6101     }
6102     hspectraEnergyvsCellID->Write();
6103     hspectraEnergyTotvsNCells->Write();
6104     hspectraEnergyTotvsNCellsST->Write();
6105     hspectraEnergyTotvsNCellsNoNoise->Write();
6106     
6107     TH1D* hspectraEnergyTot = (TH1D*)hspectraEnergyTotvsNCells->ProjectionY();
6108     hspectraEnergyTot->SetDirectory(0);
6109     TH1D* hspectraNCells = (TH1D*)hspectraEnergyTotvsNCells->ProjectionX();
6110     hspectraNCells->SetDirectory(0);
6111     TH1D* hspectraNCellsST = (TH1D*)hspectraEnergyTotvsNCellsST->ProjectionX();
6112     hspectraNCellsST->SetDirectory(0);
6113     hspectraEnergyTot->Write("hTotEnergy");
6114     hspectraNCells->Write("hNCells");
6115     hspectraNCellsST->Write("hNCellsST");
6116     
6117     RootOutputHist->cd("IndividualCells");
6118     for(ithSpectra=hSpectra.begin(); ithSpectra!=hSpectra.end(); ++ithSpectra){
6119       if (typeRO == ReadOut::Type::Caen)
6120         ithSpectra->second.FitLGHGCorr(debug,false);
6121       ithSpectra->second.WriteExt(true);
6122     }
6123     for(ithSpectraNotNoise=hSpectraNotNoise.begin(); ithSpectraNotNoise!=hSpectraNotNoise.end(); ++ithSpectraNotNoise){
6124       ithSpectraNotNoise->second.WriteExt(true);
6125     }
6126     RootOutputHist->cd("IndividualCellsNoise");
6127     for(ithSpectraNoise=hSpectraNoise.begin(); ithSpectraNoise!=hSpectraNoise.end(); ++ithSpectraNoise){
6128       ithSpectraNoise->second.WriteExt(true);
6129     }
6130     RootOutputHist->cd("IndividualCellsLocalTrigg");
6131     for(ithSpectraLocalTrigg=hSpectraLocalTrigg.begin(); ithSpectraLocalTrigg!=hSpectraLocalTrigg.end(); ++ithSpectraLocalTrigg){
6132       ithSpectraLocalTrigg->second.WriteExt(true);
6133     }
6134   RootOutputHist->Close();
6135   
6136   //**********************************************************************
6137   //********************* Plotting ***************************************
6138   //**********************************************************************
6139   
6140   TString outputDirPlots = GetPlotOutputDir();
6141   gSystem->Exec("mkdir -p "+outputDirPlots);
6142   
6143   //**********************************************************************
6144   // Create canvases for channel overview plotting
6145   //**********************************************************************
6146   Double_t textSizeRel = 0.035;
6147   StyleSettingsBasics("pdf");
6148   SetPlotStyle();
6149   
6150   TCanvas* canvas2DCorr = new TCanvas("canvasCorrPlots","",0,0,1450,1300);  // gives the page size
6151   DefaultCanvasSettings( canvas2DCorr, 0.08, 0.13, 0.045, 0.07);
6152   canvas2DCorr->SetLogz(1);
6153 
6154   TCanvas* canvas1DSimple = new TCanvas("canvas1DSimple","",0,0,1450,1300);  // gives the page size
6155   DefaultCanvasSettings( canvas1DSimple, 0.08, 0.03, 0.03, 0.07);
6156 
6157   hDeltaTime->Scale(1./evts);
6158   hDeltaTime->GetYaxis()->SetTitle("counts/event");
6159   canvas1DSimple->SetLogy();
6160   PlotSimple1D(canvas1DSimple, hDeltaTime, -10000, -10000, textSizeRel, Form("%s/TimeDiffToPrevEvent.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, "");
6161   canvas1DSimple->SetLogy(0);
6162   
6163   // overview simple plots
6164   PlotSimple2D( canvas2DCorr, hspectraHGvsCellID, -10000, -10000, textSizeRel, Form("%s/HG.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
6165   PlotSimple2D( canvas2DCorr, hspectraHGCorrvsCellIDNoise, -50, 200, -10000, textSizeRel, Form("%s/HGCorr_Noise.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true, "Local Noise triggered");
6166   PlotSimple2D( canvas2DCorr, hspectraEnergyvsCellID, -10000, -10000, textSizeRel, Form("%s/EnergyVsCellID.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
6167   PlotSimple2D( canvas2DCorr, hspectraEnergyTotvsNCells, -10000, -10000, textSizeRel, Form("%s/EnergyTotalVsNCells.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
6168 
6169   // saturated ADC per event
6170   hSaturatedADC->Scale(1./evts);
6171   hSaturatedADC->GetYaxis()->SetTitle("counts/event");
6172   PlotSimple1D(canvas1DSimple, hSaturatedADC, -10000, -10000, textSizeRel, Form("%s/SaturatedADCPerEvent.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, Form("#LT #Cells_{ADC sat.} #GT= %.1f", hSaturatedADC->GetMean()  ));
6173   hSaturatedADCvsCellID->Scale(1./evts);
6174   hSaturatedADCvsCellID->GetYaxis()->SetTitle("counts/event");
6175   PlotSimple1D(canvas1DSimple, hSaturatedADCvsCellID, -10000, -10000, textSizeRel, Form("%s/SaturatedADCPerEventvsCellID.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, "");
6176   
6177   if (typeRO == ReadOut::Type::Caen){
6178     PlotSimple2D( canvas2DCorr, hspectraHGCorrvsCellID, -10000, -10000, textSizeRel, Form("%s/HGCorr.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
6179     PlotSimple2D( canvas2DCorr, hspectraHGCorrvsCellID, 300, -10000, textSizeRel, Form("%s/HGCorr_zoomed.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
6180     PlotSimple2D( canvas2DCorr, hspectraLGvsCellID, -10000, -10000, textSizeRel, Form("%s/LG.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
6181     PlotSimple2D( canvas2DCorr, hspectraLGCorrvsCellID, -10000, -10000, textSizeRel, Form("%s/LGCorr.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
6182     PlotSimple2D( canvas2DCorr, hspectraLGCorrvsCellID, 200, -10000, textSizeRel, Form("%s/LGCorr_zoomed.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
6183     
6184     // saturated LG per event
6185     hSaturatedLG->Scale(1./evts);
6186     hSaturatedLG->GetYaxis()->SetTitle("counts/event");
6187     PlotSimple1D(canvas1DSimple, hSaturatedLG, -10000, -10000, textSizeRel, Form("%s/SaturatedLGPerEvent.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, Form("#LT #Cells_{LG sat.} #GT= %.1f ",hSaturatedLG->GetMean()));
6188     hSaturatedLGvsCellID->Scale(1./evts);
6189     hSaturatedLGvsCellID->GetYaxis()->SetTitle("counts/event");
6190     PlotSimple1D(canvas1DSimple, hSaturatedLGvsCellID, -10000, -10000, textSizeRel, Form("%s/SaturatedLGPerEventvsCellID.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, "" );
6191     
6192     // LG/HG ratio sanity checks
6193     hNCellsLGHGCorrOutsideBound->Scale(1./evts);
6194     hNCellsLGHGCorrOutsideBound->GetYaxis()->SetTitle("counts/event");
6195     PlotSimple1D(canvas1DSimple, hNCellsLGHGCorrOutsideBound, -10000, -10000, textSizeRel, Form("%s/LGHGOutSideBountPerEvent.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, Form("#LT #Cells_{LG/HG incorr} #GT= %.1f,%0.2f%s events > cell questionable",hNCellsLGHGCorrOutsideBound->GetMean(), hNCellsLGHGCorrOutsideBound->Integral(2,hNCellsLGHGCorrOutsideBound->GetNbinsX()+1)/hNCellsLGHGCorrOutsideBound->Integral(1,hNCellsLGHGCorrOutsideBound->GetNbinsX()+1)*100, "%" ));
6196     hLGHGCorrOutsideBoundCellID->Scale(1./evts);
6197     hLGHGCorrOutsideBoundCellID->GetYaxis()->SetTitle("counts/event");
6198     PlotSimple1D(canvas1DSimple, hLGHGCorrOutsideBoundCellID, -10000, -10000, textSizeRel, Form("%s/LGHGOutSideBountPerEventvsCellID.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, "" );
6199     
6200     
6201   } else if (typeRO == ReadOut::Type::Hgcroc){
6202     PlotSimple2D( canvas2DCorr, hspectraTotvsCellID, -10000, -10000, textSizeRel, Form("%s/Tot.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
6203     if(nLocalNoiseTriggs > 1) PlotSimple2D( canvas2DCorr, hspectraTotvsCellIDNoise, -50, 200, -10000, textSizeRel, Form("%s/Tot_Noise.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true, "Local Noise triggered");
6204     
6205     PlotSimple2D( canvas2DCorr, hTOANsVsCellID, -10000, setup->GetMaxCellID()+1, textSizeRel, Form("%s/TOANsvsCellID.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
6206     PlotSimple2D( canvas2DCorr, hTOACorrNsVsCellID, -10000, setup->GetMaxCellID()+1, textSizeRel, Form("%s/TOACorrNsvsCellID.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
6207     PlotSimple2D( canvas2DCorr, hSampleTOAVsCellID, (double)it->second.samples,setup->GetMaxCellID()+1, textSizeRel, Form("%s/SampleTOAvsCellID.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
6208     
6209     PlotSimple2D( canvas2DCorr, hspectraEnergyTotvsNCellsST, -10000, -10000, textSizeRel, Form("%s/EnergyTotalVsNCellsSingleTile.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
6210     if(nLocalNoiseTriggs > 1) PlotSimple2D( canvas2DCorr, hspectraEnergyTotvsNCellsNoNoise, -10000, -10000, textSizeRel, Form("%s/EnergyTotalVsNCellsNoNoise.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, kFALSE, "colz", true);
6211 
6212     // saturated TOT per event
6213     hSaturatedTOT->Scale(1./evts);
6214     hSaturatedTOT->GetYaxis()->SetTitle("counts/event");
6215     PlotSimple1D(canvas1DSimple, hSaturatedTOT, -10000, -10000, textSizeRel, Form("%s/SaturatedLGPerEvent.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, Form("#LT #Cells_{TOT sat.} #GT= %.1f ",hSaturatedTOT->GetMean()));
6216     hSaturatedTOTCellID->Scale(1./evts);
6217     hSaturatedTOTCellID->GetYaxis()->SetTitle("counts/event");
6218     PlotSimple1D(canvas1DSimple, hSaturatedTOTCellID, -10000, -10000, textSizeRel, Form("%s/SaturatedTOTCellsPerEventvsCellID.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1);
6219     
6220     
6221     for (Int_t ro = 0; ro < setup->GetNMaxROUnit()+1; ro++){
6222       for (int h = 0; h< 2; h++){      
6223           PlotSimple2D( canvas2DCorr, h2DToAvsnSample[ro][h],(double)it->second.samples, -10000, textSizeRel,
6224                             Form("%s/ToaVsNSample_Asic_%d_Half_%d.%s", outputDirPlots.Data(), ro, h, plotSuffix.Data()), 
6225                             it->second, 1, kFALSE, "colz",true, Form("Asic %d, Half %d",ro,h));
6226           h2DWaveFormHalfAsicAll[ro][h]->GetXaxis()->SetRangeUser(-25, (it->second.samples)*25);
6227           Plot2DWithProfile( canvas2DCorr, h2DWaveFormHalfAsicAll[ro][h], hWaveFormHalfAsicAll[ro][h], -10000, -10000, textSizeRel,
6228                             Form("%s/Waveform_Asic_%d_Half_%d.%s", outputDirPlots.Data(), ro, h, plotSuffix.Data()), 
6229                             it->second, 1, kFALSE, "colz",true, Form("Asic %d, Half %d",ro,h), -1);
6230       }
6231     }
6232   }
6233 
6234   hspectraEnergyTot->Scale(1./evts);
6235   hspectraEnergyTot->GetYaxis()->SetTitle("counts/event");
6236   PlotSimple1D(canvas1DSimple, hspectraEnergyTot, -10000, -10000, textSizeRel, Form("%s/EnergyTot.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, Form("#LT E_{Tot} #GT = %.1f (mip/tile eq.)",hspectraEnergyTot->GetMean() ));
6237   hspectraNCells->Scale(1./evts);
6238   hspectraNCells->GetYaxis()->SetTitle("counts/event");
6239   PlotSimple1D(canvas1DSimple, hspectraNCells, -10000, -10000, textSizeRel, Form("%s/NCells.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, Form("#LT N_{Cells} #GT = %.1f",hspectraNCells->GetMean() ));
6240   if (typeRO == ReadOut::Type::Hgcroc){
6241     PlotSimple1D(canvas1DSimple, hSampleTOA, -10000, (double)it->second.samples, textSizeRel, Form("%s/NSampleToA.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1);
6242     hspectraNCellsST->Scale(1./evts);
6243     
6244     hspectraNCellsST->GetYaxis()->SetTitle("counts/event");
6245     PlotSimple1D(canvas1DSimple, hspectraNCellsST, -10000, -10000, textSizeRel, Form("%s/NCellsSingleTiles.%s", outputDirPlots.Data(), plotSuffix.Data()), it->second, 1, Form("#LT N_{tile} #GT = %.1f",hspectraNCellsST->GetMean() ));
6246   }
6247 
6248   if (ExtPlot > 0){
6249     calib.PrintGlobalInfo();  
6250     double maxADC = 4096;
6251     if (typeRO == ReadOut::Type::Hgcroc)
6252       maxADC = 1024;
6253     
6254     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
6255     // Single layer plotting
6256     //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
6257     MultiCanvas panelPlot(detConf, "Calib");
6258     bool init1D = panelPlot.Initialize(1);
6259     MultiCanvas panelPlot2D(detConf, "Calib");
6260     bool init2D = panelPlot2D.Initialize(2);
6261       
6262     
6263     panelPlot.PlotSpectra( hSpectra, 0, -100, maxADC, 1.2, 
6264                           Form("%s/Spectra_HG" ,outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, skipPlotLayer);
6265 
6266     if (typeRO == ReadOut::Type::Caen) {
6267       if(nLocalNoiseTriggs > 1 && ExtPlot > 2) panelPlot.PlotNoiseAdvWithFits(hSpectra, hSpectraNoise, 1, -50, 100, 1.2, 
6268                                                               Form("%s/NoiseTrigg_HG" ,outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, skipPlotLayer);
6269       if(nLocalNoiseTriggs > 1 && ExtPlot > 2) panelPlot.PlotNoiseAdvWithFits(hSpectra, hSpectraNoise, 0, -50, 100, 1.2, 
6270                                                               Form("%s/NoiseTrigg_LG" ,outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, skipPlotLayer);
6271       panelPlot.PlotSpectra( hSpectra, 2, -2, 100, 1.2, 
6272                             Form("%s/Spectra_Comb" ,outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, skipPlotLayer);
6273       if (ExtPlot > 1) panelPlot2D.PlotCorrWithFits( hSpectra, 0, -20, 800, 0., 50.,
6274                                     Form("%s/LGHG_Corr",outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, skipPlotLayer);
6275       if (ExtPlot > 1) panelPlot2D.PlotCorrWithFits( hSpectra, 2, -20, 800, 0., 50.,
6276                                     Form("%s/LGLGhgeq_Corr",outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, skipPlotLayer);
6277       
6278     } else if (typeRO == ReadOut::Type::Hgcroc) {
6279       panelPlot2D.PlotCorr2DLayer(hSpectra, 4, 0, 4096, 0, 1024.,
6280                                 Form("%s/ADCTOT",outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, 0, -1, skipPlotLayer);
6281       panelPlot.PlotSpectra( hSpectra, 4, -100, 4096, 1.2,
6282                             Form("%s/Spectra_Tot" ,outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, skipPlotLayer);
6283       panelPlot.PlotMipWithFits( hSpectra, hSpectraLocalTrigg, 1, -20, maxADC, 1.2, 
6284                                   Form("%s/SpectraWithMipTrigg" ,outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, skipPlotLayer);
6285       if(nLocalNoiseTriggs > 1) panelPlot.PlotNoiseAdvWithFits(hSpectra, hSpectraNoise, 1, -20, 100, 1.2, 
6286                                                               Form("%s/NoiseTrigg" ,outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, skipPlotLayer);
6287       if(nLocalNoiseTriggs > 1) panelPlot.Plot3SpectraOverlay(hSpectra, hSpectraNotNoise, hSpectraNoise,
6288                                                               1, -20, 1024, 1.2, 
6289                                                               Form("%s/NotNoiseTrigg" ,outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib, skipPlotLayer);
6290       panelPlot.PlotTriggerPrim( hSpectraLocalTrigg, averageScalePerTile, factorMinTrigg, factorMaxTrigg, 0, 200, 1.2,
6291                                 Form("%s/TriggPrimitive" ,outputDirPlots.Data()), plotSuffix.Data(), it->second, &calib);
6292     }
6293   }
6294   return true;
6295 } // end Calibrate()
6296 
6297 //***********************************************************************************************
6298 //*********************** Save Noise triggers only ***************************************************
6299 //***********************************************************************************************
6300 bool Analyses::SaveNoiseTriggersOnly(void){
6301   std::cout<<"Save noise triggers into separate file"<<std::endl;
6302   TcalibIn->GetEntry(0);
6303   // check whether calib should be overwritten based on external text file
6304   if (OverWriteCalib){
6305     calib.ReadCalibFromTextFile(ExternalCalibFile,debug);
6306   }
6307   
6308   int evts=TdataIn->GetEntries();
6309   for(int i=0; i<evts; i++){
6310     TdataIn->GetEntry(i);
6311     if (i%5000 == 0 && i > 0 && debug > 0) std::cout << "Reading " <<  i << " / " << evts << " events" << std::endl;
6312     for(int j=0; j<event.GetNTiles(); j++){
6313       Caen* aTile=(Caen*)event.GetTile(j);
6314       // testing for noise trigger
6315       if(aTile->GetLocalTriggerBit()!= (char)2){
6316         event.RemoveTile(aTile);
6317         j--;
6318       }
6319     }
6320     RootOutput->cd();
6321     TdataOut->Fill();
6322   }
6323   TdataOut->Write();
6324   TsetupIn->CloneTree()->Write();
6325   
6326   if (IsCalibSaveToFile()){
6327     TString fileCalibPrint = RootOutputName;
6328     fileCalibPrint         = fileCalibPrint.ReplaceAll(".root","_calib.txt");
6329     calib.PrintCalibToFile(fileCalibPrint);
6330   }
6331 
6332   TcalibOut->Fill();
6333   TcalibOut->Write();
6334   RootOutput->Close();
6335   RootInput->Close();      
6336   
6337   return true;
6338 }
6339 
6340 //***********************************************************************************************
6341 //*********************** Save Noise triggers only ***************************************************
6342 //***********************************************************************************************
6343 bool Analyses::SaveCalibToOutputOnly(void){
6344   std::cout<<"Save calib into separate file: "<< GetRootCalibOutputName().Data() <<std::endl;
6345   RootCalibOutput->cd();
6346   TcalibIn->GetEntry(0);  
6347   TsetupIn->CloneTree()->Write();
6348   
6349   // check whether calib should be overwritten based on external text file
6350   if (OverWriteCalib){
6351     calib.ReadCalibFromTextFile(ExternalCalibFile,debug);
6352   }
6353   
6354   if (IsCalibSaveToFile()){
6355     TString fileCalibPrint = GetRootCalibOutputName();
6356     fileCalibPrint         = fileCalibPrint.ReplaceAll(".root","_calib.txt");
6357     calib.PrintCalibToFile(fileCalibPrint);
6358   }
6359 
6360   TcalibOut->Fill();
6361   TcalibOut->Write();
6362   RootCalibOutput->Close();
6363   
6364   return true;
6365 }
6366 
6367 //***********************************************************************************************
6368 //*********************** Save Noise triggers only ***************************************************
6369 //***********************************************************************************************
6370 bool Analyses::OverWriteSetupTree(void){
6371   std::cout<<"Rewrite original file to new output file with updated setup tree: "<< GetRootOutputName().Data() <<std::endl;
6372   RootOutput->cd();
6373   
6374   if (MapInputName.CompareTo("")== 0) {
6375       std::cerr << "ERROR: No mapping file has been provided, please make sure you do so! Aborting!" << std::endl;
6376       return false;
6377   }
6378   std::cout << "creating mapping " << std::endl;
6379   setup->Initialize(MapInputName.Data(),debug);
6380   
6381   RootSetupWrapper rswtmp=RootSetupWrapper(setup);
6382   rsw=rswtmp;
6383   TsetupOut->Fill();  
6384   TsetupOut->Write();
6385   
6386   // write Data tree to new output
6387   TdataIn->CloneTree()->Write();
6388   
6389   
6390   // check whether calib should be overwritten based on external text file
6391   TcalibIn->GetEntry(0);  
6392   if (OverWriteCalib){
6393     calib.ReadCalibFromTextFile(ExternalCalibFile,debug);
6394   }
6395   
6396   if (IsCalibSaveToFile()){
6397     TString fileCalibPrint = GetRootOutputName();
6398     fileCalibPrint         = fileCalibPrint.ReplaceAll(".root","_calib.txt");
6399     calib.PrintCalibToFile(fileCalibPrint);
6400   }
6401   TcalibOut->Fill();
6402   TcalibOut->Write();
6403   
6404   // Also copy all hists from source file
6405   TIter next(RootInput->GetListOfKeys());
6406   TKey *key;
6407 
6408   while ((key = (TKey*)next())) {
6409     // Check if the object inherits from TH1 (covers TH1F, TH1D, TH2F, etc.)
6410     TClass *cl = TClass::GetClass(key->GetClassName());
6411     if (!cl || !cl->InheritsFrom(TH1::Class())) continue;
6412 
6413     // Read the histo
6414     TH1 *hist = (TH1*)key->ReadObj();
6415         
6416     // change its ownership
6417     RootOutput->cd();
6418     TH1 *clonedHist = (TH1*)hist->Clone(); // Clone breaks dependency on sourceFile
6419 
6420     //write to destination file
6421     clonedHist->Write();
6422         
6423     // Clean up the memory for this iteration
6424     delete hist;
6425   }
6426 
6427   RootOutput->Close();
6428   
6429   return true;
6430 }
6431 
6432 //***********************************************************************************************
6433 //*********************** Save local muon triggers only ***************************************************
6434 //***********************************************************************************************
6435 bool Analyses::SaveMuonTriggersOnly(void){
6436   std::cout<<"Save local muon triggers into separate file"<<std::endl;
6437   TcalibIn->GetEntry(0);
6438     // check whether calib should be overwritten based on external text file
6439   if (OverWriteCalib){
6440     calib.ReadCalibFromTextFile(ExternalCalibFile,debug);
6441   }
6442   // Print calib info
6443   calib.PrintGlobalInfo();  
6444 
6445   
6446   ReadOut::Type typeRO = ReadOut::Type::Caen;
6447 
6448   int evts=TdataIn->GetEntries();
6449   for(int i=0; i<evts; i++){
6450     TdataIn->GetEntry(i);
6451     if (i == 0){
6452       typeRO = event.GetROtype();
6453       std::cout<< "Total number of events: " << evts << std::endl;
6454     }    
6455     if (i%5000 == 0 && i > 0 && debug > 0) std::cout << "Reading " <<  i << " / " << evts << " events" << std::endl;
6456     for(int j=0; j<event.GetNTiles(); j++){
6457       if (typeRO == ReadOut::Type::Caen) {
6458         Caen* aTile=(Caen*)event.GetTile(j);
6459         // testing for muon trigger
6460         if(aTile->GetLocalTriggerBit()!= (char)1){
6461           event.RemoveTile(aTile);
6462           j--;
6463         }
6464       } else if (typeRO == ReadOut::Type::Hgcroc){
6465         Hgcroc* aTile=(Hgcroc*)event.GetTile(j);
6466         // testing for muon trigger
6467         if(aTile->GetLocalTriggerBit()!= (char)1){
6468           event.RemoveTile(aTile);
6469           j--;
6470         }
6471       }
6472     }
6473     RootOutput->cd();
6474     TdataOut->Fill();
6475   }
6476   TdataOut->Write();
6477   TsetupIn->CloneTree()->Write();
6478   
6479   if (IsCalibSaveToFile()){
6480     TString fileCalibPrint = RootOutputName;
6481     fileCalibPrint         = fileCalibPrint.ReplaceAll(".root","_calib.txt");
6482     calib.PrintCalibToFile(fileCalibPrint);
6483   }
6484 
6485   // Print calib info
6486   calib.PrintGlobalInfo();  
6487 
6488   
6489   
6490   TcalibOut->Fill();
6491   TcalibOut->Write();
6492   RootOutput->Close();
6493   RootInput->Close();      
6494   
6495   return true;
6496 }
6497 
6498 //***********************************************************************************************
6499 //*********************** Skim HGCROC data ******************************************************
6500 //*********** write entire event if  1 cell determined fine *************************************
6501 //***********************************************************************************************
6502 bool Analyses::SkimHGCROCData(void){
6503   std::cout<<"Skim HGCROC data from pure noise"<<std::endl;
6504   TcalibIn->GetEntry(0);
6505     // check whether calib should be overwritten based on external text file
6506   if (OverWriteCalib){
6507     calib.ReadCalibFromTextFile(ExternalCalibFile,debug);
6508   }
6509 
6510   int evts=TdataIn->GetEntries();
6511   if (maxEvents == -1){
6512     maxEvents = evts;
6513   } else {
6514     std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
6515     std::cout << "ATTENTION: YOU ARE RESETTING THE MAXIMUM NUMBER OF EVENTS TO BE PROCESSED TO: " << maxEvents << ". THIS SHOULD ONLY BE USED FOR TESTING!" << std::endl;
6516     std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
6517   }
6518 
6519   long evtTrigg = 0;
6520   
6521   for(int i=0; i<evts && i < maxEvents; i++){
6522     TdataIn->GetEntry(i);
6523     if (i%5000 == 0 && i > 0 && debug > 0) std::cout << "Reading " <<  i << " / " << evts << " events" << std::endl;
6524     bool triggered = false;
6525     // Decide for the entire event before removing any tiles. A trigger on
6526     // a later tile must also retain the untriggered tiles preceding it.
6527     for(int j=0; j<event.GetNTiles(); j++){
6528       Hgcroc* aTile=(Hgcroc*)event.GetTile(j);
6529       // testing for any signal beyond noise
6530       if (debug > 3){
6531         aTile->PrintWaveFormDebugInfo(calib.GetPedestalMeanH(aTile->GetCellID()), calib.GetPedestalMeanL(aTile->GetCellID()), calib.GetPedestalSigL(aTile->GetCellID()));
6532       }
6533       
6534       if (aTile->GetRawTOA() > 0) triggered= true;
6535       if (aTile->GetLocalTriggerBit()== (char)1) triggered= true;
6536     }
6537   
6538     if (!triggered && debug == 3){
6539       for(int j=0; j<event.GetNTiles(); j++){
6540         Hgcroc* aTile=(Hgcroc*)event.GetTile(j);
6541         // testing for any signal beyond noise
6542         aTile->PrintWaveFormDebugInfo(calib.GetPedestalMeanH(aTile->GetCellID()), calib.GetPedestalMeanL(aTile->GetCellID()), calib.GetPedestalSigL(aTile->GetCellID()));
6543       }
6544     }
6545 
6546     if (!triggered){
6547       // Remove only rejected events' tiles, after completing the scan.
6548       for (int j=event.GetNTiles()-1; j>=0; --j){
6549         event.RemoveTile(event.GetTile(j));
6550       }
6551     }
6552     
6553     RootOutput->cd();
6554     if (event.GetNTiles() > 0){
6555       evtTrigg++;
6556       TdataOut->Fill();
6557     }
6558   }
6559   TdataOut->Write();
6560   TsetupIn->CloneTree()->Write();
6561   
6562   std::cout << "Evts in: " << maxEvents << "\t skimmed: " << evtTrigg << std::endl;
6563   
6564   if (IsCalibSaveToFile()){
6565     TString fileCalibPrint = RootOutputName;
6566     fileCalibPrint         = fileCalibPrint.ReplaceAll(".root","_calib.txt");
6567     calib.PrintCalibToFile(fileCalibPrint);
6568   }
6569 
6570   TcalibOut->Fill();
6571   TcalibOut->Write();
6572   RootOutput->Close();
6573   RootInput->Close();      
6574   
6575   return true;
6576 }
6577 
6578 //***********************************************************************************************
6579 //*********************** Create output files ***************************************************
6580 //***********************************************************************************************
6581 bool Analyses::CreateOutputRootFile(void){
6582   if(Overwrite){
6583     std::cout << "overwriting exisiting output file" << std::endl;
6584     RootOutput=new TFile(RootOutputName.Data(),"RECREATE");
6585   } else{
6586     std::cout << "creating output file" << std::endl;
6587     RootOutput = new TFile(RootOutputName.Data(),"CREATE");
6588   }
6589   if(RootOutput->IsZombie()){
6590     std::cout<<"Error opening '"<<RootOutput<<"'no reachable path? Exist without force mode to overwrite?..."<<std::endl;
6591     return false;
6592   }
6593   return true;
6594 }
6595 
6596 //***********************************************************************************************
6597 //*********************** Create output files ***************************************************
6598 //***********************************************************************************************
6599 bool Analyses::CreateOutputRootHistFile(void){
6600   std::cout << "Additional Output with histos being created: " << RootOutputNameHist.Data() << std::endl;
6601   if(Overwrite){
6602     std::cout << "overwriting exisiting output file" << std::endl;
6603     RootOutputHist=new TFile(RootOutputNameHist.Data(),"RECREATE");
6604   } else{
6605     std::cout << "creating output file" << std::endl;
6606     RootOutputHist = new TFile(RootOutputNameHist.Data(),"CREATE");
6607   }
6608   if(RootOutputHist->IsZombie()){
6609     std::cout<<"Error opening '"<<RootOutputHist<<"'no reachable path? Exist without force mode to overwrite?..."<<std::endl;
6610     return false;
6611   }
6612   return true;
6613 }
6614 
6615 //***********************************************************************************************
6616 //*********************** Read external bad channel map *****************************************
6617 //***********************************************************************************************
6618 std::map<int,short> Analyses::ReadExternalBadChannelMap(void){
6619   
6620   std::cout << "Reading in external mapping file" << std::endl;
6621   std::map<int,short> bcmap;
6622   
6623   std::ifstream bcmapFile;
6624   bcmapFile.open(ExternalBadChannelMap,std::ios_base::in);
6625   if (!bcmapFile) {
6626     std::cout << "ERROR: file " << ExternalBadChannelMap.Data() << " not found!" << std::endl;
6627     return bcmap;
6628   }
6629 
6630   for( TString tempLine; tempLine.ReadLine(bcmapFile, kTRUE); ) {
6631     // check if line should be considered
6632     if (tempLine.BeginsWith("%") || tempLine.BeginsWith("#")){
6633       continue;
6634     }
6635     if (debug > 1) std::cout << tempLine.Data() << std::endl;
6636 
6637     // Separate the string according to tabulators
6638     TObjArray *tempArr  = tempLine.Tokenize(" ");
6639     if(tempArr->GetEntries()<2){
6640       if (debug > 1) std::cout << "nothing to be done" << std::endl;
6641       delete tempArr;
6642       continue;
6643     } 
6644     
6645     int mod     = ((TString)((TObjString*)tempArr->At(0))->GetString()).Atoi();
6646     int layer   = ((TString)((TObjString*)tempArr->At(1))->GetString()).Atoi();
6647     int row     = ((TString)((TObjString*)tempArr->At(2))->GetString()).Atoi();
6648     int col     = ((TString)((TObjString*)tempArr->At(3))->GetString()).Atoi();
6649     short bc    = short(((TString)((TObjString*)tempArr->At(4))->GetString()).Atoi());
6650     
6651     int cellID  = setup->GetCellID( row, col, layer, mod);    
6652                 
6653     if (debug > 1) std::cout << "cellID " << cellID << "\t BC status: " << bc<< std::endl;
6654     bcmap[cellID]=bc;
6655   }
6656   std::cout << "registered " << bcmap.size() << " bad channels!" << std::endl;
6657   return bcmap;  
6658   
6659 }