Skip to content
Snippets Groups Projects
LHCf_reader.cpp 15.85 KiB
/** @defgroup ana Analysis
*   @ingroup ana
*   @file LHCf_reader.cpp
*   @brief Implementation of LHCf_reader.
*
*  Function definitions for LHCf_reader are provided.
*  This class reads a rootfile with raw waveforms stored in LHCf format
*  that are processed by LHCf DAQ.
*  The first scope is just to provide a 1-1 conversion to our pdrf format
*
*  @author Riccardo Longo, Yftach Moyal
*  @bug No known bugs.
*/

#include "LHCf_reader.h"

#include <string>
#include <stdio.h>


/** @brief Constructor for LHCf_reader.
 */
LHCf_reader::LHCf_reader(  const std::string& _fileName,
                           const unsigned int _nCh,
                           const unsigned int _nSamples )
  : DataReader2021( _nCh, _nSamples, _fileName, 0 )
{
  //m_fileName = _fileName;
  //m_nCh = 32;
}

/** @brief Destructor for LHCf_reader.
 */
LHCf_reader::~LHCf_reader( ){

}

void LHCf_reader::InitializeHistograms(){

  std::string chName;
  for( int i = 0; i < m_nCh; i++){
      chName = Form( "Channel%d", i );
      m_v_histoChannels.push_back( new TH1D(chName.c_str(), chName.c_str(), m_nSamp, 0, m_nSamp));
      chName = Form( "ChannelCorr%d", i );
      m_v_histoChannelsCorr.push_back( new TH1D(chName.c_str(), chName.c_str(), m_nSamp, 0, m_nSamp));
  }

}
void LHCf_reader::OpenFile( void ){

    std::cout << "Opening file  " << m_fNameIn << std::endl;
    if ( m_fNameIn == "ND"){
      std::cerr << "File name not defined. Going to crash!"  << std::endl;
      return;
    }
    m_filePointer = TFile::Open( m_fNameIn.c_str() );
    m_readTrigger1 = new LHCf_Trigger1((TTree*)m_filePointer->Get( "Trigger1" ));

    InitializeHistograms();
    std::cout << "File " << m_fNameIn << " opened successfully! " << std::endl;

}

void LHCf_reader::OpenFileName( std::string _fileName ){

    std::cout << "Opening file  " << m_fNameIn << std::endl;
    m_fNameIn = _fileName;
    m_filePointer = TFile::Open( m_fNameIn.c_str() );
    //m_trigger1 =
    m_readTrigger1 = new LHCf_Trigger1((TTree*)m_filePointer->Get( "Trigger1" ));

    InitializeHistograms();
    std::cout << "File " << m_fNameIn << " opened successfully! " << std::endl;
}

// Get 3 32 bit dwords and return 8 Ch sample values of the group Ch 0,1,2…7
std::vector<float>  LHCf_reader::GetGroupSample(unsigned int dwrd_0, unsigned int dwrd_1, unsigned int dwrd_2){
  /*
   Get 3 32 bit dwords and return 8 Ch sample values
   of the group Ch 0,1,2…7.

   Details:
   To shift x by n bits to the left (make it bigger):
   x*2^n
   ===============================================
   To read the m bits n positions from the beginning of the word x
    x/(2^n)%2^m
    ===============================================
  */
  std::vector<float> sample;
  sample.push_back(dwrd_0%4096);                                 // CH0
  sample.push_back((dwrd_0/4096)%4096);                          // CH1
  sample.push_back((dwrd_0/16777216)%4096 ^ (dwrd_1%16)*256);    // CH2
  sample.push_back((dwrd_1/16)%4096);                            // CH3
  sample.push_back((dwrd_1/65536)%4096);                         // CH4
  sample.push_back((dwrd_1/268435456)%4096 ^ (dwrd_2%256)*16);   // CH5
  sample.push_back((dwrd_2/256)%4096);                           // CH6
  sample.push_back((dwrd_2/1048576)%4096);                       // CH7
  return sample;
}

void LHCf_reader::ShowEvent( int iEvent ){

  m_readTrigger1->Show( iEvent );
}

void LHCf_reader::ConvertFile(){
   std::string outputDir =  Form("%s/ProcessedLHCf",std::getenv("JZCaPA"));
   gSystem->Exec( Form("mkdir -p %s", outputDir.c_str() ) );
   std::string base_filename = m_fNameIn.substr(m_fNameIn.find_last_of("/\\") + 1);
   std::string of = Form("%s/%s",outputDir.c_str() ,base_filename.c_str() );
   if (m_debug) printf(" output file:%s\n",of.c_str());
   TFile* out_file = TFile::Open(of.c_str(),"RECREATE"); 
   TObject *obj;
   TKey *key;
   TTree* tree[5];
   TIter next( m_filePointer->GetListOfKeys());
   int id = 0;
   bool readCurrent = 0;
   int RunNumber;
   int evt;

   // Get runNumber
  std::string fname_str(base_filename.c_str());
  std::string result = fname_str.substr(0, fname_str.find_last_of("."));
  RunNumber =  atoi(result.substr(result.find_last_not_of("0123456789") + 1).c_str());

    for ( int iCh = 0; iCh < m_nCh; iCh++){
      std::vector < float > v_buffer, v_buffer2;
      v_buffer.resize( m_nSamp );
      v_buffer2.resize( m_nSamp );
      m_v_Channels.push_back( v_buffer );
      m_v_Channels_Corrected.push_back( v_buffer2 );
    }


   while ((key = (TKey *) next())) {
      obj = m_filePointer->Get(key->GetName()); // copy object to memory
      if (strcmp(key->GetClassName(),"TTree")) continue;
      if (m_debug) printf(" found object:%s\n",key->GetName());
      if (!strcmp(((TTree*)obj)->GetName(),"Trigger1")){
        if (readCurrent) continue;
        readCurrent = 1;
        // Do Things with Trigger1
        TTree* tree_to_read = (TTree*)obj;
        if (m_debug) printf(" Nubmer of entries:%lld\n",tree_to_read->GetEntries());
        // Deactivate the branch which needs to be processed
        tree_to_read->SetBranchStatus("ZDCH",0);
        // Clone skimmed
        if (m_debug) printf(" About to clone LHCf branches\n");
        tree[id] = tree_to_read->CloneTree(0); 
        tree[id]->CopyEntries(tree_to_read);
        tree[id]->SetBranchStatus("*",0);
        if (m_debug) printf(" Successfully cloned LHCf branches\n"); 
        // Reactivate ZDCH
        tree_to_read->SetBranchStatus("*",0);

        tree_to_read->SetBranchStatus("ZDCH",1);
        //Create run number and event number branches

        tree[id]->Branch("RunNumber", &RunNumber, "RunNumber/I" );
        tree[id]->Branch("EventNumber", &evt, "EventNumber/I" );
        // Generate new Branches for unpacking
        if (m_debug) printf(" About to generate ZDCH WF branches\n");
        for (int ch=0;ch<m_nChPerGroup*m_nGroups;ch++){
          tree[id]->Branch( Form( "RawSignal%d", ch), "std::vector<float>", &m_v_Channels_Corrected.at(ch) );
        }
        if (m_debug) printf(" Finished generating ZDCH WF branches\n");
        // Run over all events and unpack, as per the 2 event shift
        int MaxEvents = tree_to_read->GetEntries();
        for(evt=0;evt<MaxEvents;evt++){
          // Get Samples from evt+2
          if ((MaxEvents-evt) < 3) continue;// Fill Empty
          GetEventWaveforms(evt+2);
           
          tree[id]->Fill();
        }
        tree[id]->SetEntries(MaxEvents);
        tree[id]->SetName("tree"); // Temporary to see if solves JZCaPA issue
      }else{
        if (m_debug) printf(" Writing to TTree with ID: %d\n",id);
        tree[id] = ((TTree*)obj)->CloneTree();
      }
      id++;
  
   }
   if (m_filePointer) m_filePointer->Close();
   
   if (m_debug) printf(" Moving into new file.\n");
   out_file->cd();
   if (m_debug) printf(" Writing into new file.\n");
   out_file->Write();
   if (m_debug) printf(" Finished writing.\n");
   out_file->Close();
}


void LHCf_reader::GetEventWaveforms(int iEvent){
    m_v_Channels.clear();
    m_v_Channels_Corrected.clear();

    m_readTrigger1->GetEntry( iEvent );
    bool trg_beam = false;
    bool trg_pede = false;
    trg_beam = (m_readTrigger1->GPI0_GPI0[0] >> 8) & 0x1;
    trg_pede = (m_readTrigger1->GPI0_GPI0[0] >> 5) & 0x1;

    //Checking trigger ADCs
    double adc[2];
    adc[0] = m_readTrigger1->ADC2_ADC2[0] - m_readTrigger1->ADC2_ADC2[32];// trg.scin 1
    adc[1] = m_readTrigger1->ADC2_ADC2[2] - m_readTrigger1->ADC2_ADC2[34];// trg.scin 2


    if(trg_pede) {
      std::cout << "PEDESTAL TRIGGER - SKIP " << std::endl;
     // return;
    }
    if(trg_beam){
       std::cout << "BEAM TRIGGER " << std::endl;
     }

    for ( int iCh = 0; iCh < m_nCh; iCh++){
      std::vector < float > v_buffer, v_buffer2;
      v_buffer.resize( m_nSamp );
      v_buffer2.resize( m_nSamp );
      m_v_Channels.push_back( v_buffer );
      m_v_Channels_Corrected.push_back( v_buffer2 );
    }

    //Retrieving calibration file from Util folder
    std::string calibFile = std::getenv("JZCaPA") + std::string("/Utils/calib_0234_2G_0.dat");

    caen_correction *cc;
    cc = new caen_correction ( calibFile.c_str() );

    unsigned int curser = 4;
    unsigned int n_words_for_group_data_extraction;
    unsigned int c_stop_flag;

    //NSI - Noise subtraction implementation
    unsigned int index_cell[m_nGroups];
    // For group 1
    for (int gid = 0; gid < m_nGroups; gid++){
      n_words_for_group_data_extraction = m_readTrigger1->ZDCH_ZDCH[curser]%4096;
      index_cell[gid] = (m_readTrigger1->ZDCH_ZDCH[curser]/1048576)%4096;
      if(m_debug)
        std::cout << "GID: " << gid << " n_words_for_group_data_extraction: " << n_words_for_group_data_extraction << std::endl;
      //std::cout << "TR: " << (m_readTrigger1->ZDCH_ZDCH[curser]/4096)%2 << std::endl;
      curser += 1;
      c_stop_flag = curser + n_words_for_group_data_extraction;
    // run over the dwords and extract each sample
      int iBin = 0;
      if(m_debug)
        std::cout << "PRE --> CURSER: " << curser << " - CSTOPFLAG: " << c_stop_flag << std::endl;

      for (int dummy = 0; curser < c_stop_flag; curser+=3){
        std::vector < float > sample_vec = GetGroupSample(m_readTrigger1->ZDCH_ZDCH[curser],m_readTrigger1->ZDCH_ZDCH[curser+1],m_readTrigger1->ZDCH_ZDCH[curser+2]);
        // store samples
        for ( int iSamp = 0; iSamp < m_nChPerGroup; iSamp++){
          m_v_Channels.at( (gid * m_nChPerGroup) + iSamp ).at(iBin) = sample_vec.at(iSamp);
        }
        iBin++;
      }
      if(m_debug)
        std::cout << "POST --> CURSER: " << curser << " - CSTOPFLAG: " << c_stop_flag << std::endl;
     // Move to next group data words
     curser += 1;
    }

    // Perform signal correction using firmware values
    cc->init(index_cell, m_nGroups, m_v_Channels);
    for(int iCh = 0; iCh < m_nChPerGroup*m_nGroups; iCh++){
      for(int iSamp = 0; iSamp < m_nSamp; iSamp++){
        m_v_Channels_Corrected.at( iCh ).at( iSamp ) = cc->caen_corrected( iSamp, iCh );
      }
    }

}

void LHCf_reader::ReadEvents( int iStartEvent, int iEndEvent ){

  if( iStartEvent == -1 ) iStartEvent = 0;
  if( iEndEvent == -1 ) iEndEvent = m_readTrigger1->GetEntries();
  if( iEndEvent-iStartEvent > GetMaxEvents() && iEndEvent != -1
      && GetMaxEvents() != -1 && iStartEvent != -1)
      iEndEvent = iStartEvent+GetMaxEvents();


  TCanvas* ct = new TCanvas("ct", "ct", 3200, 4800);
  ct->Divide(4,m_nGroups*2);

  for( int iEvent = iStartEvent ; iEvent < iEndEvent; iEvent++){

    m_readTrigger1->GetEntry( iEvent );
    bool trg_beam = false;
    bool trg_pede = false;
    trg_beam = (m_readTrigger1->GPI0_GPI0[0] >> 8) & 0x1;
    trg_pede = (m_readTrigger1->GPI0_GPI0[0] >> 5) & 0x1;

    //Checking trigger ADCs
    double adc[2];
    adc[0] = m_readTrigger1->ADC2_ADC2[0] - m_readTrigger1->ADC2_ADC2[32];// trg.scin 1
    adc[1] = m_readTrigger1->ADC2_ADC2[2] - m_readTrigger1->ADC2_ADC2[34];// trg.scin 2

    if(trg_pede) {
      std::cout << "PEDESTAL TRIGGER - SKIP " << std::endl;
      continue;
    }
    if(trg_beam){
       std::cout << "BEAM TRIGGER " << std::endl;
     }

    for ( int iCh = 0; iCh < m_nCh; iCh++){
      std::vector < float > v_buffer, v_buffer2;
      v_buffer.resize( m_nSamp );
      v_buffer2.resize( m_nSamp );
      m_v_Channels.push_back( v_buffer );
      m_v_Channels_Corrected.push_back( v_buffer2 );
    }

    //Retrieving calibration file from Util folder
    std::string calibFile = std::getenv("JZCaPA") + std::string("/Utils/calib_0234_2G_0.dat");

    caen_correction *cc;
    cc = new caen_correction ( calibFile.c_str() );

    int nPerGroup = 8;
    unsigned int curser = 4;
    unsigned int n_words_for_group_data_extraction;
    unsigned int c_stop_flag;

    //NSI - Noise subtraction implementation
    unsigned int index_cell[m_nGroups];
    // For group 1
    for (int gid = 0; gid < m_nGroups; gid++){
      n_words_for_group_data_extraction = m_readTrigger1->ZDCH_ZDCH[curser]%4096;
      index_cell[gid] = (m_readTrigger1->ZDCH_ZDCH[curser]/1048576)%4096;
      if(m_debug)
        std::cout << "GID: " << gid << " n_words_for_group_data_extraction: " << n_words_for_group_data_extraction << std::endl;
      //std::cout << "TR: " << (m_readTrigger1->ZDCH_ZDCH[curser]/4096)%2 << std::endl;
      curser += 1;
      c_stop_flag = curser + n_words_for_group_data_extraction;
    // run over the dwords and extract each sample
      int iBin = 0;
      if(m_debug)
        std::cout << "PRE --> CURSER: " << curser << " - CSTOPFLAG: " << c_stop_flag << std::endl;

      for (int dummy = 0; curser < c_stop_flag; curser+=3){
        std::vector < float > sample_vec = GetGroupSample(m_readTrigger1->ZDCH_ZDCH[curser],m_readTrigger1->ZDCH_ZDCH[curser+1],m_readTrigger1->ZDCH_ZDCH[curser+2]);
        // store samples
        for ( int iSamp = 0; iSamp < nPerGroup; iSamp++){
          m_v_Channels.at( (gid * nPerGroup) + iSamp ).at(iBin) = sample_vec.at(iSamp);
          m_v_histoChannels.at( (gid * nPerGroup) + iSamp )->Fill( iBin, sample_vec.at(iSamp));
        }
        iBin++;
      }
      if(m_debug)
        std::cout << "POST --> CURSER: " << curser << " - CSTOPFLAG: " << c_stop_flag << std::endl;
     // Move to next group data words
     curser += 1;
    }
    cc->init(index_cell, m_nGroups, m_v_Channels);
    for(int iCh = 0; iCh < nPerGroup*m_nGroups; iCh++){
      for(int iSamp = 0; iSamp < m_nSamp; iSamp++){
        m_v_Channels_Corrected.at( iCh ).at( iSamp ) = cc->caen_corrected( iSamp, iCh );
        m_v_histoChannelsCorr.at( iCh )->Fill( iSamp, m_v_Channels_Corrected.at( iCh ).at( iSamp )+400);
      }
    }

    for( int iCh = 0; iCh  < nPerGroup*m_nGroups; iCh++){
      ct->cd( iCh+1 );
      m_v_histoChannels.at(iCh)->Draw( "HISTO" );
      m_v_histoChannelsCorr.at(iCh)->SetLineColor(kRed);
      m_v_histoChannelsCorr.at(iCh)->Draw( "HISTOSAME" );
      if(iCh < 8) m_v_histoChannels.at(iCh)->GetYaxis()->SetRangeUser( 3100, 4100 );
      if(iCh >= 8) m_v_histoChannels.at(iCh)->GetYaxis()->SetRangeUser( 1800, 2800 );
    }
    /* The following block works only if you don't set range User above.
    // Also - it's so basic to be otrageous
    sci1Corr->Fill( adc[0], m_v_histoChannels.at( 0 )->GetMinimum( ) );
    sci2Corr->Fill( adc[1], m_v_histoChannels.at( 1 )->GetMinimum( ) );
    if(m_debug) std::cout << "In Time WF: " << m_v_histoChannels.at( 0 )->GetMinimum( ) << " - " << m_v_histoChannels.at( 1 )->GetMinimum( ) << std::endl;
    if(m_debug) std::cout << "In Time ADC: " << adc[0] << " - " << adc[1] << std::endl;
    if(iEvent > 0){
      m_readTrigger1->GetEntry( iEvent-1 );
      adc[0] = m_readTrigger1->ADC2_ADC2[0] - m_readTrigger1->ADC2_ADC2[32];// trg.scin 1
      adc[1] = m_readTrigger1->ADC2_ADC2[2] - m_readTrigger1->ADC2_ADC2[34];// trg.scin 2
      p_sci1Corr->Fill( adc[0], m_v_histoChannels.at( 0 )->GetMinimum( ) );
      p_sci2Corr->Fill( adc[1], m_v_histoChannels.at( 1 )->GetMinimum( ) );
      if(m_debug)
        std::cout << "Previous Trigger ADC: " << adc[0] << " - " << adc[1] << std::endl;

    }
    if(iEvent > 1){
      m_readTrigger1->GetEntry( iEvent-2 );
      adc[0] = m_readTrigger1->ADC2_ADC2[0] - m_readTrigger1->ADC2_ADC2[32];// trg.scin 1
      adc[1] = m_readTrigger1->ADC2_ADC2[2] - m_readTrigger1->ADC2_ADC2[34];// trg.scin 2
      pp_sci1Corr->Fill( adc[0], m_v_histoChannels.at( 0 )->GetMinimum( ) );
      pp_sci2Corr->Fill( adc[1], m_v_histoChannels.at( 1 )->GetMinimum( ) );
      if(m_debug)
        std::cout << "Previous x2 Trigger ADC: " << adc[0] << " - " << adc[1] << std::endl;
    }
    */
    std::string svname;
    svname = Form( "Event%d.png", iEvent );
    ct->Print(svname.c_str());
    for( int iCh = 0; iCh  < m_v_histoChannels.size(); iCh++){
      m_v_histoChannels.at(iCh)->Reset();
      m_v_histoChannelsCorr.at(iCh)->Reset();
    }
  }


}

void LHCf_reader::VisualizeChannels( ){

  TCanvas* cc = new TCanvas("cc", "cc", 3200, 800);
  cc->Divide(8,m_nGroups);
  for( int iCh = 0; iCh  < m_v_histoChannels.size(); iCh++){
    cc->cd( iCh+1 );
    m_v_histoChannels.at(iCh)->Draw( "HISTO" );
    m_v_histoChannels.at(iCh)->GetYaxis()->SetRangeUser( 0, 4096 );
  }
}