Skip to content
Snippets Groups Projects
THcCherenkov.cxx 24.4 KiB
Newer Older
/** \class THcCherenkov
    \ingroup Detectors

\brief Class for gas Cherenkov detectors

#include "THcCherenkov.h"
#include "THcHodoscope.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 "THaApparatus.h"
#include "VarDef.h"
#include "VarType.h"
#include "THaTrack.h"
#include "TClonesArray.h"
#include "TMath.h"
#include "THaTrackProj.h"
#include "THcHallCSpectrometer.h"
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <iostream>
using namespace std;

using std::cout;
using std::cin;
using std::endl;
using std::setw;
using std::setprecision;

//_____________________________________________________________________________
THcCherenkov::THcCherenkov( const char* name, const char* description,
                            THaApparatus* apparatus ) :
  hcana::ConfigLogging<THaNonTrackingDetector>(name,description,apparatus)
{
  // Normal constructor with name and description
  frAdcPedRaw       = new TClonesArray("THcSignalHit", MaxNumCerPmt*MaxNumAdcPulse);
  frAdcPulseIntRaw  = new TClonesArray("THcSignalHit", MaxNumCerPmt*MaxNumAdcPulse);
  frAdcPulseAmpRaw  = new TClonesArray("THcSignalHit", MaxNumCerPmt*MaxNumAdcPulse);
  frAdcPulseTimeRaw = new TClonesArray("THcSignalHit", MaxNumCerPmt*MaxNumAdcPulse);
  frAdcPed          = new TClonesArray("THcSignalHit", MaxNumCerPmt*MaxNumAdcPulse);
  frAdcPulseInt     = new TClonesArray("THcSignalHit", MaxNumCerPmt*MaxNumAdcPulse);
  frAdcPulseAmp     = new TClonesArray("THcSignalHit", MaxNumCerPmt*MaxNumAdcPulse);
  frAdcPulseTime    = new TClonesArray("THcSignalHit", MaxNumCerPmt*MaxNumAdcPulse);
  fAdcErrorFlag     = new TClonesArray("THcSignalHit", MaxNumCerPmt*MaxNumAdcPulse);

  fNumAdcHits         = vector<Int_t>    (MaxNumCerPmt, 0.0);
  fNumGoodAdcHits     = vector<Int_t>    (MaxNumCerPmt, 0.0);
  fNumTracksMatched   = vector<Int_t>    (MaxNumCerPmt, 0.0);
  fNumTracksFired     = vector<Int_t>    (MaxNumCerPmt, 0.0);
  fNpe                = vector<Double_t> (MaxNumCerPmt, 0.0);
  fGoodAdcPed         = vector<Double_t> (MaxNumCerPmt, 0.0);
  fGoodAdcMult         = vector<Double_t> (MaxNumCerPmt, 0.0);
  fGoodAdcHitUsed         = vector<Double_t> (MaxNumCerPmt, 0.0);
  fGoodAdcPulseInt    = vector<Double_t> (MaxNumCerPmt, 0.0);
  fGoodAdcPulseIntRaw = vector<Double_t> (MaxNumCerPmt, 0.0);
  fGoodAdcPulseAmp    = vector<Double_t> (MaxNumCerPmt, 0.0);
  fGoodAdcPulseTime   = vector<Double_t> (MaxNumCerPmt, 0.0);
  fGoodAdcTdcDiffTime   = vector<Double_t> (MaxNumCerPmt, 0.0);
}

//_____________________________________________________________________________
THcCherenkov::THcCherenkov( ) :
  hcana::ConfigLogging<THaNonTrackingDetector>()
{
  // Constructor
  frAdcPedRaw       = NULL;
  frAdcPulseIntRaw  = NULL;
  frAdcPulseAmpRaw  = NULL;
  frAdcPed          = NULL;
  frAdcPulseInt     = NULL;
  frAdcPulseAmp     = NULL;
  frAdcPulseTime    = NULL;
//_____________________________________________________________________________
THcCherenkov::~THcCherenkov()
{
  // Destructor
  delete frAdcPedRaw;       frAdcPedRaw       = NULL;
  delete frAdcPulseIntRaw;  frAdcPulseIntRaw  = NULL;
  delete frAdcPulseAmpRaw;  frAdcPulseAmpRaw  = NULL;
  delete frAdcPulseTimeRaw; frAdcPulseTimeRaw = NULL;
  delete frAdcPed;          frAdcPed          = NULL;
  delete frAdcPulseInt;     frAdcPulseInt     = NULL;
  delete frAdcPulseAmp;     frAdcPulseAmp     = NULL;
  delete frAdcPulseTime;    frAdcPulseTime    = NULL;
  delete fAdcErrorFlag;     fAdcErrorFlag     = NULL;

  DeleteArrays();
}

//_____________________________________________________________________________
void THcCherenkov::InitArrays()
{
  fGain     = NULL;
  fPedSum   = NULL;
  fPedSum2  = NULL;
}
//_____________________________________________________________________________
void THcCherenkov::DeleteArrays()
{
  delete [] fGain; fGain = NULL;

  // 6 Gev variables
  delete [] fPedSum;   fPedSum   = NULL;
  delete [] fPedSum2;  fPedSum2  = NULL;
  delete [] fPedLimit; fPedLimit = NULL;
  delete [] fPedMean;  fPedMean  = NULL;
  delete [] fPedCount; fPedCount = NULL;
  delete [] fPed;      fPed      = NULL;
  delete [] fThresh;   fThresh   = NULL;
}

//_____________________________________________________________________________
THaAnalysisObject::EStatus THcCherenkov::Init( const TDatime& date )
{
Eric Pooser's avatar
Eric Pooser committed
  // cout << "THcCherenkov::Init for: " << GetName() << endl;
  string EngineDID = string(GetApparatus()->GetName()).substr(0, 1) + GetName();
  std::transform(EngineDID.begin(), EngineDID.end(), EngineDID.begin(), ::toupper);
  if(gHcDetectorMap->FillMap(fDetMap, EngineDID.c_str()) < 0) {
    static const char* const here = "Init()";
    Error(Here(here), "Error filling detectormap for %s.", EngineDID.c_str());
  if((status = THaNonTrackingDetector::Init( date )))
  // Should probably put this in ReadDatabase as we will know the
  // maximum number of hits after setting up the detector map
  InitHitList(fDetMap, "THcCherenkovHit", fDetMap->GetTotNumChan()+1,
	      0, fADC_RefTimeCut);

  THcHallCSpectrometer *app=dynamic_cast<THcHallCSpectrometer*>(GetApparatus());
   if(  !app ||
      !(fglHod = dynamic_cast<THcHodoscope*>(app->GetDetector("hod"))) ) {
    static const char* const here = "ReadDatabase()";
    Warning(Here(here),"Hodoscope \"%s\" not found. ","hod");
  }

 fPresentP = 0;
  THaVar* vpresent = gHaVars->Find(Form("%s.present",GetApparatus()->GetName()));
  if(vpresent) {
    fPresentP = (Bool_t *) vpresent->GetValuePointer();
  }
  return fStatus = kOK;
}

//_____________________________________________________________________________
Int_t THcCherenkov::ReadDatabase( const TDatime& date )
{
  // This function is called by THaDetectorBase::Init() once at the beginning
  // of the analysis.

Eric Pooser's avatar
Eric Pooser committed
  // cout << "THcCherenkov::ReadDatabase for: " << GetName() << endl; // Ahmed
  string prefix = string(GetApparatus()->GetName()).substr(0, 1) + GetName();
  std::transform(prefix.begin(), prefix.end(), prefix.begin(), ::tolower);
  CreateMissReportParms(prefix.c_str());

  fNRegions = 4;  // Defualt if not set in paramter file

  DBRequest list_1[] = {
    {"_tot_pmts", &fNelem, kInt},
    {"_num_regions",      &fNRegions,         kInt},
  gHcParms->LoadParmValues(list_1, prefix.c_str());
  _logger->info("Created Cherenkov detector {}.{} with {} PMTs",GetApparatus()->GetName(), GetName(), fNelem);
  //cout << "Created Cherenkov detector " << GetApparatus()->GetName() << "."
  //     << GetName() << " with " << fNelem << " PMTs" << endl;
  // 6 GeV pedestal paramters
Zafar's avatar
Zafar committed
  fPedLimit = new Int_t[fNelem];
  fGain     = new Double_t[fNelem];
  fPedMean  = new Double_t[fNelem];
  fAdcTimeWindowMin =  new Double_t[fNelem];
  fAdcTimeWindowMax=  new Double_t[fNelem];
  // Region parameters
  fRegionsValueMax = fNRegions * 8;
  fRegionValue     = new Double_t[fRegionsValueMax];
  DBRequest list[]={
    {"_ped_limit",        fPedLimit,          kInt,     (UInt_t) fNelem, optional},
    {"_adc_to_npe",       fGain,              kDouble,  (UInt_t) fNelem},
    {"_red_chi2_min",     &fRedChi2Min,       kDouble},
    {"_red_chi2_max",     &fRedChi2Max,       kDouble},
    {"_beta_min",         &fBetaMin,          kDouble},
    {"_beta_max",         &fBetaMax,          kDouble},
    {"_enorm_min",        &fENormMin,         kDouble},
    {"_enorm_max",        &fENormMax,         kDouble},
    {"_dp_min",           &fDpMin,            kDouble},
    {"_dp_max",           &fDpMax,            kDouble},
    {"_mirror_zpos",      &fMirrorZPos,       kDouble},
    {"_npe_thresh",       &fNpeThresh,        kDouble},
    {"_debug_adc",        &fDebugAdc,         kInt, 0, 1},
    {"_adcTimeWindowMin", fAdcTimeWindowMin, kDouble,(UInt_t) fNelem,1},
    {"_adcTimeWindowMax", fAdcTimeWindowMax, kDouble, (UInt_t) fNelem,1},
    {"_adc_tdc_offset",   &fAdcTdcOffset,     kDouble, 0, 1},
    {"_region",           &fRegionValue[0],   kDouble,  (UInt_t) fRegionsValueMax},
    {"_adcrefcut",        &fADC_RefTimeCut,   kInt,    0, 1},
  for (Int_t i=0;i<fNelem;i++) {
    fAdcTimeWindowMin[i]=-1000.;
    fAdcTimeWindowMax[i]=1000.;
  }
  fDebugAdc = 0; // Set ADC debug parameter to false unless set in parameter file
  fADC_RefTimeCut = 0;
  gHcParms->LoadParmValues((DBRequest*)&list, prefix.c_str());
Eric Pooser's avatar
Eric Pooser committed
  // if (fDebugAdc) cout << "Cherenkov ADC Debug Flag Set To TRUE" << endl;
Zafar Ahmed's avatar
Zafar Ahmed committed

Eric Pooser's avatar
Eric Pooser committed
  // cout << "Track Matching Parameters for: " << GetName() << endl;
  // for (Int_t iregion = 0; iregion < fNRegions; iregion++) {
  //   cout << "Region = " << iregion + 1 << endl;
  //   for (Int_t ivalue = 0; ivalue < 8; ivalue++)
  //     cout << fRegionValue[GetIndex(iregion, ivalue)] << "  ";
  //   cout << endl;
  // }
  // Create arrays to hold pedestal results
  InitializePedestals();

  return kOK;
}

//_____________________________________________________________________________
Int_t THcCherenkov::DefineVariables( EMode mode )
{
  // Initialize global variables for histogramming and tree
Eric Pooser's avatar
Eric Pooser committed
  // cout << "THcCherenkov::DefineVariables called for: " << GetName() << endl;

  if( mode == kDefine && fIsSetup ) return kOK;
  fIsSetup = ( mode == kDefine );
  // Register variables in global list
    RVarDef vars[] = {
      {"numAdcHits",      "Number of ADC Hits Per PMT", "fNumAdcHits"},        // Cherenkov occupancy
      {"totNumAdcHits",   "Total Number of ADC Hits",   "fTotNumAdcHits"},     // Cherenkov multiplicity
      {"adcPedRaw",       "Raw ADC pedestals",          "frAdcPedRaw.THcSignalHit.GetData()"},
      {"adcPulseIntRaw",  "Raw ADC pulse integrals",    "frAdcPulseIntRaw.THcSignalHit.GetData()"},
      {"adcPulseAmpRaw",  "Raw ADC pulse amplitudes",   "frAdcPulseAmpRaw.THcSignalHit.GetData()"},
      {"adcPulseTimeRaw", "Raw ADC pulse times",        "frAdcPulseTimeRaw.THcSignalHit.GetData()"},
      {"adcPed",          "ADC pedestals",              "frAdcPed.THcSignalHit.GetData()"},
      {"adcPulseInt",     "ADC pulse integrals",        "frAdcPulseInt.THcSignalHit.GetData()"},
      {"adcPulseAmp",     "ADC pulse amplitudes",       "frAdcPulseAmp.THcSignalHit.GetData()"},
      {"adcPulseTime",    "ADC pulse times",            "frAdcPulseTime.THcSignalHit.GetData()"},
      { 0 }
    };
    DefineVarsFromList( vars, mode);
  } //end debug statement

  RVarDef vars[] = {
    {"adcCounter",   "ADC counter numbers",            "frAdcPulseIntRaw.THcSignalHit.GetPaddleNumber()"},
    {"adcErrorFlag", "Error Flag for When FPGA Fails", "fAdcErrorFlag.THcSignalHit.GetData()"},
    {"numGoodAdcHits",    "Number of Good ADC Hits Per PMT", "fNumGoodAdcHits"},    // Cherenkov occupancy
    {"totNumGoodAdcHits", "Total Number of Good ADC Hits",   "fTotNumGoodAdcHits"}, // Cherenkov multiplicity
    {"numTracksMatched",    "Number of Tracks Matched Per Region",       "fNumTracksMatched"},
    {"numTracksFired",      "Number of Tracks that Fired Per Region",    "fNumTracksFired"},
    {"totNumTracksMatched", "Total Number of Tracks Matched Per Region", "fTotNumTracksMatched"},
    {"totNumTracksFired",   "Total Number of Tracks that Fired",         "fTotNumTracksFired"},

    {"xAtCer",       "Track X at Cherenkov mirror",    "fXAtCer"},
    {"yAtCer",       "Track Y at Cherenkov mirror",    "fYAtCer"},

    {"npe",          "Number of PEs",                  "fNpe"},
    {"npeSum",       "Total Number of PEs",            "fNpeSum"},

    {"goodAdcPed",          "Good ADC pedestals",           "fGoodAdcPed"},
    {"goodAdcMult",          "Good ADC Multiplicity",           "fGoodAdcMult"},
    {"goodAdcHitUsed",          "Good ADC Hit Used",           "fGoodAdcHitUsed"},
    {"goodAdcPulseInt",     "Good ADC pulse integrals",     "fGoodAdcPulseInt"},
    {"goodAdcPulseIntRaw",  "Good ADC raw pulse integrals", "fGoodAdcPulseIntRaw"},
    {"goodAdcPulseAmp",     "Good ADC pulse amplitudes",    "fGoodAdcPulseAmp"},
    {"goodAdcPulseTime",    "Good ADC pulse times",         "fGoodAdcPulseTime"},
     {"goodAdcTdcDiffTime",    "Good Hodo Start - ADC pulse times",         "fGoodAdcTdcDiffTime"},
   { 0 }
  return DefineVarsFromList(vars, mode);
}
//_____________________________________________________________________________
void THcCherenkov::Clear(Option_t* opt)
{
  // Clear the hit lists
  fNhits               = 0;
  fTotNumAdcHits       = 0;
  fTotNumGoodAdcHits   = 0;
  fTotNumTracksMatched = 0;
  fTotNumTracksFired   = 0;
  frAdcPedRaw->Clear();
  frAdcPulseIntRaw->Clear();
  frAdcPulseAmpRaw->Clear();
  frAdcPulseTimeRaw->Clear();
  frAdcPulseInt->Clear();
  frAdcPulseAmp->Clear();
  frAdcPulseTime->Clear();
  fAdcErrorFlag->Clear();

  for (UInt_t ielem = 0; ielem < fNumAdcHits.size(); ielem++)
    fNumAdcHits.at(ielem) = 0;
  for (UInt_t ielem = 0; ielem < fNumGoodAdcHits.size(); ielem++)
    fNumGoodAdcHits.at(ielem) = 0;
  for (UInt_t ielem = 0; ielem < fNumTracksMatched.size(); ielem++)
    fNumTracksMatched.at(ielem) = 0;
  for (UInt_t ielem = 0; ielem < fNumTracksFired.size(); ielem++)
    fNumTracksFired.at(ielem) = 0;
  for (UInt_t ielem = 0; ielem < fGoodAdcPed.size(); ielem++) {
    fGoodAdcPed.at(ielem)         = 0.0;
    fGoodAdcMult.at(ielem)         = 0.0;
    fGoodAdcHitUsed.at(ielem)         = 0.0;
    fGoodAdcPulseInt.at(ielem)    = 0.0;
    fGoodAdcPulseIntRaw.at(ielem) = 0.0;
    fGoodAdcPulseAmp.at(ielem)    = 0.0;
    fGoodAdcPulseTime.at(ielem)   = kBig;
    fGoodAdcTdcDiffTime.at(ielem)   = kBig;
}

//_____________________________________________________________________________
Int_t THcCherenkov::Decode( const THaEvData& evdata )
{
  // Get the Hall C style hitlist (fRawHitList) for this event
  Bool_t present = kTRUE;	// Suppress reference time warnings
  if(fPresentP) {		// if this spectrometer not part of trigger
    present = *fPresentP;
  }
  fNhits = DecodeToHitList(evdata, !present);

  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
  }

  while(ihit < fNhits) {
    THcCherenkovHit* hit         = (THcCherenkovHit*) fRawHitList->At(ihit);
    Int_t            npmt        = hit->fCounter;
    THcRawAdcHit&    rawAdcHit   = hit->GetRawAdcHitPos();
    for (UInt_t thit = 0; thit < rawAdcHit.GetNPulses(); thit++) {
      ((THcSignalHit*) frAdcPedRaw->ConstructedAt(nrAdcHits))->Set(npmt, rawAdcHit.GetPedRaw());
      ((THcSignalHit*) frAdcPed->ConstructedAt(nrAdcHits))->Set(npmt, rawAdcHit.GetPed());
      ((THcSignalHit*) frAdcPulseIntRaw->ConstructedAt(nrAdcHits))->Set(npmt, rawAdcHit.GetPulseIntRaw(thit));
      ((THcSignalHit*) frAdcPulseInt->ConstructedAt(nrAdcHits))->Set(npmt, rawAdcHit.GetPulseInt(thit));
      ((THcSignalHit*) frAdcPulseAmpRaw->ConstructedAt(nrAdcHits))->Set(npmt, rawAdcHit.GetPulseAmpRaw(thit));
      ((THcSignalHit*) frAdcPulseAmp->ConstructedAt(nrAdcHits))->Set(npmt, rawAdcHit.GetPulseAmp(thit));
      ((THcSignalHit*) frAdcPulseTimeRaw->ConstructedAt(nrAdcHits))->Set(npmt, rawAdcHit.GetPulseTimeRaw(thit));
      ((THcSignalHit*) frAdcPulseTime->ConstructedAt(nrAdcHits))->Set(npmt, rawAdcHit.GetPulseTime(thit)+fAdcTdcOffset);
      if (rawAdcHit.GetPulseAmpRaw(thit) > 0)  ((THcSignalHit*) fAdcErrorFlag->ConstructedAt(nrAdcHits))->Set(npmt, 0);
      if (rawAdcHit.GetPulseAmpRaw(thit) <= 0) ((THcSignalHit*) fAdcErrorFlag->ConstructedAt(nrAdcHits))->Set(npmt, 1);

      ++nrAdcHits;
      fTotNumAdcHits++;
      fNumAdcHits.at(npmt-1) = npmt;
    }
    ihit++;
  }
  return ihit;
}

//_____________________________________________________________________________
Int_t THcCherenkov::ApplyCorrections( void )
{
  return(0);
}

//_____________________________________________________________________________
Int_t THcCherenkov::CoarseProcess( TClonesArray&  )
  Double_t StartTime = 0.0;
  if( fglHod ) StartTime = fglHod->GetStartTime();
  // Loop over the elements in the TClonesArray
  for(Int_t ielem = 0; ielem < frAdcPulseInt->GetEntries(); ielem++) {

    Int_t    npmt         = ((THcSignalHit*) frAdcPulseInt->ConstructedAt(ielem))->GetPaddleNumber() - 1;
    Double_t pulsePed     = ((THcSignalHit*) frAdcPed->ConstructedAt(ielem))->GetData();
    Double_t pulseInt     = ((THcSignalHit*) frAdcPulseInt->ConstructedAt(ielem))->GetData();
    Double_t pulseIntRaw  = ((THcSignalHit*) frAdcPulseIntRaw->ConstructedAt(ielem))->GetData();
    Double_t pulseAmp     = ((THcSignalHit*) frAdcPulseAmp->ConstructedAt(ielem))->GetData();
    Double_t pulseTime    = ((THcSignalHit*) frAdcPulseTime->ConstructedAt(ielem))->GetData();
   Double_t adctdcdiffTime = StartTime-pulseTime;
     Bool_t   errorFlag    = ((THcSignalHit*) fAdcErrorFlag->ConstructedAt(ielem))->GetData();
    Bool_t   pulseTimeCut = adctdcdiffTime > fAdcTimeWindowMin[npmt] && adctdcdiffTime < fAdcTimeWindowMax[npmt];
    // By default, the last hit within the timing cut will be considered "good"
    if (!errorFlag && pulseTimeCut) {
      fGoodAdcPed.at(npmt)         = pulsePed;
      fGoodAdcHitUsed.at(npmt)         = ielem+1;
      fGoodAdcPulseInt.at(npmt)    = pulseInt;
      fGoodAdcPulseIntRaw.at(npmt) = pulseIntRaw;
      fGoodAdcPulseAmp.at(npmt)    = pulseAmp;
      fGoodAdcPulseTime.at(npmt)   = pulseTime;
      fGoodAdcTdcDiffTime.at(npmt)   = adctdcdiffTime;

      fNpe.at(npmt) = fGain[npmt]*fGoodAdcPulseInt.at(npmt);
      fNpeSum += fNpe.at(npmt);

      fTotNumGoodAdcHits++;
      fNumGoodAdcHits.at(npmt) = npmt + 1;
    }
  }
  return 0;
}

//_____________________________________________________________________________
Int_t THcCherenkov::FineProcess( TClonesArray& tracks )
{

  Int_t nTracks = tracks.GetLast() + 1;

  for (Int_t itrack = 0; itrack < nTracks; itrack++) {

    THaTrack* track = dynamic_cast<THaTrack*> (tracks[itrack]);
    if (track->GetIndex() != 0) continue;  // Select the best track

    Double_t trackChi2    = track->GetChi2();
    Int_t    trackNDoF    = track->GetNDoF();
    Double_t trackRedChi2 = trackChi2/trackNDoF;
    Double_t trackBeta    = track->GetBeta();
    Double_t trackEnergy  = track->GetEnergy();
    Double_t trackMom     = track->GetP();
    Double_t trackDp      = track->GetDp();
    Double_t trackENorm   = trackEnergy/trackMom;
    Double_t trackXfp     = track->GetX();
    Double_t trackYfp     = track->GetY();
    Double_t trackTheta   = track->GetTheta();
    Double_t trackPhi     = track->GetPhi();

    Bool_t trackRedChi2Cut = trackRedChi2 > fRedChi2Min && trackRedChi2 < fRedChi2Max;
    Bool_t trackBetaCut    = trackBeta    > fBetaMin    && trackBeta    < fBetaMax;
    Bool_t trackENormCut   = trackENorm   > fENormMin   && trackENorm   < fENormMax;
    Bool_t trackDpCut      = trackDp      > fDpMin      && trackDp      < fDpMax;
        fXAtCer = trackXfp + trackTheta * fMirrorZPos;
        fYAtCer = trackYfp + trackPhi   * fMirrorZPos;
    if (trackRedChi2Cut && trackBetaCut && trackENormCut && trackDpCut) {
        // Project the track to the Cherenkov mirror planes

        // cout << "Cherenkov Detector: " << GetName() << " has fNRegions = " << fNRegions << endl;
        // cout << "nTracks = " << nTracks << "\t" << "trackChi2 = " << trackChi2
        // 	   << "\t" << "trackNDof = " << trackNDoF << "\t" << "trackRedChi2 = " << trackRedChi2 << endl;
        // cout << "trackBeta = " << trackBeta << "\t" << "trackEnergy = " << trackEnergy << "\t"
        // 	   << "trackMom = " << trackMom << "\t" << "trackENorm = " << trackENorm << endl;
        // cout << "trackXfp = " << trackXfp << "\t" << "trackYfp = " << trackYfp << "\t"
        // 	   << "trackTheta = " << trackTheta << "\t" << "trackPhi = " << trackPhi << endl;
        // cout << "fMirrorZPos = " << fMirrorZPos << "\t" << "fXAtCer = " << fXAtCer << "\t" << "fYAtCer = " << fYAtCer << endl;
        // cout << "=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:" << endl;

        for (Int_t iregion = 0; iregion < fNRegions; iregion++) {

            if ((TMath::Abs(fRegionValue[GetIndex(iregion, 0)] - fXAtCer)   < fRegionValue[GetIndex(iregion, 4)]) &&
                (TMath::Abs(fRegionValue[GetIndex(iregion, 1)] - fYAtCer)   < fRegionValue[GetIndex(iregion, 5)]) &&
                (TMath::Abs(fRegionValue[GetIndex(iregion, 2)] - trackTheta) < fRegionValue[GetIndex(iregion, 6)]) &&
                (TMath::Abs(fRegionValue[GetIndex(iregion, 3)] - trackPhi)   < fRegionValue[GetIndex(iregion, 7)])) {

                fTotNumTracksMatched++;
                fNumTracksMatched.at(iregion) = iregion + 1;

                if (fNpeSum > fNpeThresh) {
                    fTotNumTracksFired++;
                    fNumTracksFired.at(iregion) = iregion + 1;
                }  // NPE threshold cut
            }  // Regional cuts
        }  // Loop over regions
    }  // Tracking cuts
  }  // Track loop
  return 0;
}

//_____________________________________________________________________________
void THcCherenkov::InitializePedestals()
{
  fNPedestalEvents = 0;
  fMinPeds         = 500; 		// In engine, this is set in parameter file
  fPedSum          = new Int_t [fNelem];
  fPedSum2         = new Int_t [fNelem];
  fPedCount        = new Int_t [fNelem];
  fPed             = new Double_t [fNelem];
  fThresh          = new Double_t [fNelem];
  for(Int_t i = 0; i < fNelem; i++) {
    fPedSum[i]   = 0;
    fPedSum2[i]  = 0;
Zafar's avatar
Zafar committed
    fPedCount[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 nadc = hit->GetRawAdcHitPos().GetPulseIntRaw();
Zafar's avatar
Zafar committed
    if(nadc <= fPedLimit[element]) {
      fPedSum[element]  += nadc;
Zafar's avatar
Zafar committed
      fPedSum2[element] += nadc*nadc;
      fPedCount[element]++;
      if(fPedCount[element] == fMinPeds/5) {
	fPedLimit[element] = 100 + fPedSum[element]/fPedCount[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++) {
Zafar's avatar
Zafar committed
    // PMT tubes
    fPed[i] = ((Double_t) fPedSum[i]) / TMath::Max(1, fPedCount[i]);
    fThresh[i] = fPed[i] + 15;

    // 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) {
Zafar's avatar
Zafar committed
      if(fPedCount[i] > fMinPeds) {
	fPedMean[i] = fPed[i];
      }
    }
  }
  //  cout << " " << endl;

//_____________________________________________________________________________
Int_t THcCherenkov::GetIndex(Int_t nRegion, Int_t nValue)
{
  return fNRegions * nValue + nRegion;
//_____________________________________________________________________________
void THcCherenkov::Print(const Option_t* opt) const
{
  THaNonTrackingDetector::Print(opt);
  // Print out the pedestals
  cout << endl;
  cout << "Cherenkov Pedestals" << endl;
  // Ahmed
Zafar's avatar
Zafar committed
  cout << "No.   ADC" << endl;
  for(Int_t i=0; i<fNelem; i++)
Zafar's avatar
Zafar committed
    cout << " " << i << "    " << fPed[i] << endl;
//_____________________________________________________________________________
Double_t THcCherenkov::GetCerNPE()
{
  return fNpeSum;
//_____________________________________________________________________________
Int_t THcCherenkov::End(THaRunBase* run)
{
  MissReport(Form("%s.%s", GetApparatus()->GetName(), GetName()));
  return 0;
}
ClassImp(THcCherenkov)
////////////////////////////////////////////////////////////////////////////////