Skip to content
Snippets Groups Projects
THcCherenkov.cxx 14.6 KiB
Newer Older
  • Learn to ignore specific revisions
  • ///////////////////////////////////////////////////////////////////////////////////////
    //                                                                                   //
    // THcCherenkov                                                                      //
    //                                                                                   //
    // Class for an Cherenkov detector consisting of onw pair of PMT's                   //
    //                                                                                   //
    
    // Zafar Ahmed. Updated on December 24 2013.                                         //
    // Four more variables are added.                                                    //
    //                                                                                   //
    // npe               Total Number of photo electrons                                 //
    // hit_1             Total hits in adc 1                                             //
    // hit_2             Total hits in adc 2                                             //
    // hit               Total hits in adc 1 and 2                                       //
    //                                                                                   //
    
    // Comment:No need to cahnge the Map file but may need to change the parameter file  //
    //                                                                                   //
    // This code is written for following variables:                                     //
    //                                                                                   //
    // Variable Name     Description                                                     //
    // adc_1             Raw value of adc 1                                              //
    // adc_2             Raw value of adc 2                                              //
    // adc_p_1           Pedestal substracted value of adc 1                             //
    // adc_p_2           Pedestal substracted value of adc 2                             //
    // npe_1             Number of photo electrons of adc 1                              //
    // npe_2             Number of photo electrons of adc 2                              //
    //                                                                                   //
    ///////////////////////////////////////////////////////////////////////////////////////
    
    #include "THcCherenkov.h"
    #include "TClonesArray.h"
    #include "THcSignalHit.h"
    #include "THaEvData.h"
    #include "THaDetMap.h"
    #include "THcDetectorMap.h"
    #include "THcGlobals.h"
    #include "THaCutList.h"
    #include "THcParmList.h"
    #include "THcHitList.h"
    #include "VarDef.h"
    #include "VarType.h"
    #include "THaTrack.h"
    #include "TClonesArray.h"
    #include "TMath.h"
    
    #include "THaTrackProj.h"
    
    #include <cstring>
    #include <cstdio>
    #include <cstdlib>
    #include <iostream>
    
    using namespace std;
    
    using std::cout;
    using std::cin;
    using std::endl;
    
    #include <iomanip>
    using std::setw;
    using std::setprecision;
    
    //_____________________________________________________________________________
    THcCherenkov::THcCherenkov( const char* name, const char* description,
    				  THaApparatus* apparatus ) :
      THaNonTrackingDetector(name,description,apparatus)
    {
      // Normal constructor with name and description
      fPosADCHits = new TClonesArray("THcSignalHit",16);
    
    //  fTrackProj = new TClonesArray( "THaTrackProj", 5 );
    }
    
    //_____________________________________________________________________________
    THcCherenkov::THcCherenkov( ) :
      THaNonTrackingDetector()
    {
      // Constructor
    }
    
    //_____________________________________________________________________________
    THcCherenkov::~THcCherenkov()
    {
      // Destructor
      delete [] fPosGain;
      delete [] fPosPedLimit;
      delete [] fPosPedMean;
    }
    
    //_____________________________________________________________________________
    THaAnalysisObject::EStatus THcCherenkov::Init( const TDatime& date )
    {
      static const char* const here = "Init()";
    
      cout << "THcCherenkov::Init " << GetName() << endl;
    
      // Should probably put this in ReadDatabase as we will know the
      // maximum number of hits after setting up the detector map
      THcHitList::InitHitList(fDetMap, "THcCherenkovHit", 100); // 100 is max hits
    
      EStatus status;
      if( (status = THaNonTrackingDetector::Init( date )) )
        return fStatus=status;
    
      // Will need to determine which apparatus it belongs to and use the
      // appropriate detector ID in the FillMap call
      if( gHcDetectorMap->FillMap(fDetMap, "HCER") < 0 ) {
        Error( Here(here), "Error filling detectormap for %s.", 
    	     "HCER");
          return kInitError;
      }
    
      return fStatus = kOK;
    }
    
    //_____________________________________________________________________________
    Int_t THcCherenkov::ReadDatabase( const TDatime& date )
    {
      // This function is called by THaDetectorBase::Init() once at the beginning
      // of the analysis.
    
      cout << "THcCherenkov::ReadDatabase " << GetName() << endl; // Ahmed
    
      char prefix[2];
    
      prefix[0]=tolower(GetApparatus()->GetName()[0]);
      prefix[1]='\0';
    
      fNelem = 2;      // Default if not defined                                                                    
      
      fPosGain = new Double_t[fNelem];
      fPosPedLimit = new Int_t[fNelem];
      fPosPedMean = new Double_t[fNelem];
      
      DBRequest list[]={
        {"cer_adc_to_npe", fPosGain, kDouble, fNelem},              // Ahmed
        {"cer_ped_limit", fPosPedLimit, kInt, fNelem},              // Ahmed
        {0}
      };
      gHcParms->LoadParmValues((DBRequest*)&list,prefix);
    
      fIsInit = true;
    
      // Create arrays to hold pedestal results
      InitializePedestals();
    
      return kOK;
    }
    
    //_____________________________________________________________________________
    Int_t THcCherenkov::DefineVariables( EMode mode )
    {
      // Initialize global variables for histogramming and tree
    
      cout << "THcCherenkov::DefineVariables called " << GetName() << endl;
    
      if( mode == kDefine && fIsSetup ) return kOK;
      fIsSetup = ( mode == kDefine );
      
      // Register variables in global list
    
      // Do we need to put the number of pos/neg TDC/ADC hits into the variables?
      // No.  They show up in tree as Ndata.H.aero.postdchits for example
    
      RVarDef vars[] = {
    
        {"adc_1",    "Raw First ADC Amplitude",                  "fA_1"},
        {"adc_2",    "Raw Second ADC Amplitude",                 "fA_2"},
        {"adc_p_1",  "Pedestal Subtracted First ADC Amplitude",  "fA_p_1"},
        {"adc_p_2",  "Pedestal Subtracted Second ADC Amplitude", "fA_p_2"},
        {"npe_1",    "PEs of First Tube",                        "fNpe_1"},
        {"npe_2",    "PEs of Second Tube",                       "fNpe_2"},
        {"npe",      "Total number of PEs",                      "fNpe"},
        {"hit_1",    "ADC hits First Tube",                      "fNHits_1"},
        {"hit_2",    "ADC hits Second Tube",                     "fNHits_2"},
        {"hit",      "Total ADC hits",                           "fNHits"},
    
        {"posadchits", "List of Positive ADC hits","fPosADCHits.THcSignalHit.GetPaddleNumber()"},
        { 0 }
      };
    
      return DefineVarsFromList( vars, mode );
    }
    //_____________________________________________________________________________
    inline 
    void THcCherenkov::Clear(Option_t* opt)
    {
      // Clear the hit lists
      fPosADCHits->Clear();
    
      // Clear Cherenkov variables  from h_trans_cer.f
      
      fNhits = 0;	     // Don't really need to do this.  (Be sure this called before Decode)
    
      fA_1 = 0;
      fA_2 = 0;
      fA_p_1 = 0;
      fA_p_2 = 0;
      fNpe_1 = 0;
      fNpe_2 = 0;
    
      fNpe = 0;
      fNHits_1 = 0;
      fNHits_2 = 0;
      fNHits = 0;
    
    
    }
    
    //_____________________________________________________________________________
    Int_t THcCherenkov::Decode( const THaEvData& evdata )
    {
      // Get the Hall C style hitlist (fRawHitList) for this event
      fNhits = THcHitList::DecodeToHitList(evdata);
    
      if(gHaCuts->Result("Pedestal_event")) {
    
        AccumulatePedestals(fRawHitList);
    
        fAnalyzePedestals = 1;	// Analyze pedestals first normal events
        return(0);
      }
    
      if(fAnalyzePedestals) {
         
        CalculatePedestals();
       
        fAnalyzePedestals = 0;	// Don't analyze pedestals next event
      }
    
    
      Int_t ihit = 0;
      Int_t nPosADCHits=0;
      while(ihit < fNhits) {
        THcCherenkovHit* hit = (THcCherenkovHit *) fRawHitList->At(ihit);
        
        // ADC positive hit
        if(hit->fADC_pos >  0) {
          THcSignalHit *sighit = (THcSignalHit*) fPosADCHits->ConstructedAt(nPosADCHits++);
          sighit->Set(hit->fCounter, hit->fADC_pos);
        }
    
        ihit++;
      }
      return ihit;
    }
    
    //_____________________________________________________________________________
    Int_t THcCherenkov::ApplyCorrections( void )
    {
      return(0);
    }
    
    //_____________________________________________________________________________
    Int_t THcCherenkov::CoarseProcess( TClonesArray&  ) //tracks
    {
      /* 
         ------------------------------------------------------------------------------------------------------------------
         h_trans_cer.f code:
    
          hcer_num_hits = 0                                      <--- clear event
          do tube=1,hcer_num_mirrors                             
            hcer_npe(tube) = 0.                                  <--- clear event
            hcer_adc(tube) = 0.                                  <--- clear event
          enddo
          hcer_npe_sum = 0.                                      <--- clear event
          do nhit = 1, hcer_tot_hits                             <--- loop over total hits. Very first line of this method
            tube = hcer_tube_num(nhit)                           <--- tube is number of PMT on either side and it is this 
    	                                                          line:  Int_t npmt = hit->fCounter - 1
            hcer_adc(tube) = hcer_raw_adc(nhit) - hcer_ped(tube) <--- This is done above:
                                                                      fA_Pos_p[npmt] = hit->fADC_pos - fPosPedMean[npmt];
                                                                      fA_Neg_p[npmt] = hit->fADC_neg - fNegPedMean[npmt];
            if (hcer_adc(tube) .gt. hcer_width(tube)) then       <--- This needs to convert in hcana
              hcer_num_hits = hcer_num_hits + 1
              hcer_tube_num(hcer_num_hits) = tube
              hcer_npe(tube) = hcer_adc(tube) * hcer_adc_to_npe(tube)
              hcer_npe_sum = hcer_npe_sum + hcer_npe(tube)
            endif
          enddo
         ------------------------------------------------------------------------------------------------------------------
        */
    
      for(Int_t ihit=0; ihit < fNhits; ihit++) {
        THcCherenkovHit* hit = (THcCherenkovHit *) fRawHitList->At(ihit); // nhit = 1, hcer_tot_hits
    
        // Pedestal subtraction and gain adjustment
    
        // An ADC value of less than zero occurs when that particular
        // channel has been sparsified away and has not been read. 
        // The NPE for that tube will be assigned zero by this code.
        // An ADC value of greater than 8192 occurs when the ADC overflows on
        // an input that is too large. Tubes with this characteristic will
        // be assigned NPE = 100.0.
        Int_t npmt = hit->fCounter - 1;                             // tube = hcer_tube_num(nhit)
        // Should probably check that npmt is in range
        if ( ihit != npmt )
          cout << "ihit != npmt " << endl;
    
        if ( npmt == 0 ) {
          fA_1 = hit->fADC_pos;
          fA_p_1 = hit->fADC_pos - fPosPedMean[npmt];
          if ( ( fA_p_1 > 50 ) && ( hit->fADC_pos < 8000 ) ) {
    	fNpe_1 = fPosGain[npmt]*fA_p_1;
    
          } else if (  hit->fADC_pos > 8000 ) {
    	fNpe_1 = 100.0;
          } else {
    	fNpe_1 = 0.0;
          }
        }
        
        if ( npmt == 1 ) {
          fA_2 = hit->fADC_pos;
          fA_p_2 = hit->fADC_pos - fPosPedMean[npmt];
          if ( ( fA_p_2 > 50 ) && ( hit->fADC_pos < 8000 ) ) {
    	fNpe_2 = fPosGain[npmt]*fA_p_2;
    
          } else if (  hit->fADC_pos > 8000 ) {
    	fNpe_2 = 100.0;
          } else {
    	fNpe_2 = 0.0;
          }
        }
    
        
        if ( npmt == 0 ) {
          fNpe += fNpe_1;
          fNHits += fNHits_1;
        }
        
        if ( npmt == 1 ) {
          fNpe += fNpe_2;
          fNHits += fNHits_2;
        }
        
    
      ApplyCorrections();
    
      return 0;
    }
    
    //_____________________________________________________________________________
    Int_t THcCherenkov::FineProcess( TClonesArray& tracks )
    {
    
      return 0;
    }
    
    //_____________________________________________________________________________
    void THcCherenkov::InitializePedestals( )
    {
      fNPedestalEvents = 0;
      fMinPeds = 500; 		// In engine, this is set in parameter file
      fPosPedSum = new Int_t [fNelem];
      fPosPedSum2 = new Int_t [fNelem];
      fPosPedLimit = new Int_t [fNelem];
      fPosPedCount = new Int_t [fNelem];
    
      fPosPed = new Double_t [fNelem];
      fPosThresh = new Double_t [fNelem];
      for(Int_t i=0;i<fNelem;i++) {
        fPosPedSum[i] = 0;
        fPosPedSum2[i] = 0;
        fPosPedLimit[i] = 1000;	// In engine, this are set in parameter file
        fPosPedCount[i] = 0;
      }
    
    }
    
    //_____________________________________________________________________________
    void THcCherenkov::AccumulatePedestals(TClonesArray* rawhits)
    {
      // Extract data from the hit list, accumulating into arrays for
      // calculating pedestals
    
      Int_t nrawhits = rawhits->GetLast()+1;
    
      Int_t ihit = 0;
      while(ihit < nrawhits) {
        THcCherenkovHit* hit = (THcCherenkovHit *) rawhits->At(ihit);
    
        Int_t element = hit->fCounter - 1;
        Int_t adcpos = hit->fADC_pos;
        if(adcpos <= fPosPedLimit[element]) {
          fPosPedSum[element] += adcpos;
          fPosPedSum2[element] += adcpos*adcpos;
          fPosPedCount[element]++;
          if(fPosPedCount[element] == fMinPeds/5) {
    	fPosPedLimit[element] = 100 + fPosPedSum[element]/fPosPedCount[element];
          }
        }
        ihit++;
      }
    
      fNPedestalEvents++;
    
      return;
    }
    
    //_____________________________________________________________________________
    void THcCherenkov::CalculatePedestals( )
    {
      // Use the accumulated pedestal data to calculate pedestals
      // Later add check to see if pedestals have drifted ("Danger Will Robinson!")
      //  cout << "Plane: " << fPlaneNum << endl;
      for(Int_t i=0; i<fNelem;i++) {
        
        // Positive tubes
        fPosPed[i] = ((Double_t) fPosPedSum[i]) / TMath::Max(1, fPosPedCount[i]);
        fPosThresh[i] = fPosPed[i] + 15;
    
        //    cout << i+1 << " " << fPosPed[i] << " " << fNegPed[i] << endl;
    
        // Just a copy for now, but allow the possibility that fXXXPedMean is set
        // in a parameter file and only overwritten if there is a sufficient number of
        // pedestal events.  (So that pedestals are sensible even if the pedestal events were
        // not acquired.)
        if(fMinPeds > 0) {
          if(fPosPedCount[i] > fMinPeds) {
    	fPosPedMean[i] = fPosPed[i];
          }
        }
      }
      //  cout << " " << endl;
      
    }
    void THcCherenkov::Print( const Option_t* opt) const {
      THaNonTrackingDetector::Print(opt);
    
      // Print out the pedestals
    
      cout << endl;
      cout << "Cherenkov Pedestals" << endl;
    
      // Ahmed
      cout << "No.   Pos" << endl;
      for(Int_t i=0; i<fNelem; i++){
        cout << " " << i << "    " << fPosPed[i] << endl;
      }
    
      cout << endl;
    }
    
    ClassImp(THcCherenkov)
    ////////////////////////////////////////////////////////////////////////////////