From e786cf8c7923f01c982dbf70da79c40fa5e7c405 Mon Sep 17 00:00:00 2001
From: "Stephen A. Wood" <saw@jlab.org>
Date: Wed, 15 Nov 2017 23:21:15 -0500
Subject: [PATCH] Allow reference times for FADC pulse times

---
 src/THcHitList.cxx    | 59 ++++++++++++++++++++++++++++++++++++-------
 src/THcRawAdcHit.cxx  | 40 +++++++++++++++++++++++++++--
 src/THcRawAdcHit.h    |  5 ++++
 src/THcRawHodoHit.cxx |  7 ++---
 4 files changed, 97 insertions(+), 14 deletions(-)

diff --git a/src/THcHitList.cxx b/src/THcHitList.cxx
index 9346bb8..a48d755 100644
--- a/src/THcHitList.cxx
+++ b/src/THcHitList.cxx
@@ -144,16 +144,33 @@ Int_t THcHitList::DecodeToHitList( const THaEvData& evdata ) {
   // Get the indexed reference times for this event
   for(Int_t i=0;i<fNRefIndex;i++) {
     if(fRefIndexMaps[i].defined) {
-      if(evdata.GetNumHits(fRefIndexMaps[i].crate,
-			   fRefIndexMaps[i].slot,
-			   fRefIndexMaps[i].channel) > 0) {
-	// Only take first hit in this reference channel
-	fRefIndexMaps[i].reftime =
-	  evdata.GetData(fRefIndexMaps[i].crate,fRefIndexMaps[i].slot,
-			 fRefIndexMaps[i].channel,0);
-	fRefIndexMaps[i].hashit = kTRUE;
+      if(evdata.IsMultifunction(fRefIndexMaps[i].crate,
+				fRefIndexMaps[i].slot)) { // Multifunction module (e.g. FADC)
+	// Make sure at least one pulse
+	if(evdata.GetNumEvents(Decoder::kPulseTime, fRefIndexMaps[i].crate,
+			       fRefIndexMaps[i].slot,
+			       fRefIndexMaps[i].channel) > 0) {
+	  fRefIndexMaps[i].reftime =
+	    evdata.GetData(Decoder::kPulseTime,fRefIndexMaps[i].crate,fRefIndexMaps[i].slot,
+			   fRefIndexMaps[i].channel,0);
+	  fRefIndexMaps[i].hashit = kTRUE;
+	} else {
+	  fRefIndexMaps[i].hashit = kFALSE;
+	}
       } else {
-	fRefIndexMaps[i].hashit = kFALSE;
+	if(evdata.GetNumHits(fRefIndexMaps[i].crate,
+			     fRefIndexMaps[i].slot,
+			     fRefIndexMaps[i].channel) > 0) {
+	  // Only take first hit in this reference channel
+	  // Here we need to check if it is a multifunction type and get the time
+	  // if it is.
+	  fRefIndexMaps[i].reftime =
+	    evdata.GetData(fRefIndexMaps[i].crate,fRefIndexMaps[i].slot,
+			   fRefIndexMaps[i].channel,0);
+	  fRefIndexMaps[i].hashit = kTRUE;
+	} else {
+	  fRefIndexMaps[i].hashit = kFALSE;
+	}
       }
     }
   }
@@ -265,6 +282,30 @@ Int_t THcHitList::DecodeToHitList( const THaEvData& evdata ) {
 					  evdata.GetData(Decoder::kPulsePedestal, d->crate, d->slot, chan, ipulse),
 					  evdata.GetData(Decoder::kPulsePeak, d->crate, d->slot, chan, ipulse));
 	}
+	// Get the reference time for the FADC pulse time
+	if(d->refchan >= 0) {	// Reference time for the slot
+	  if(evdata.GetNumEvents(Decoder::kPulseIntegral, d->crate, d->slot, d->refchan) > 0) {
+	    Int_t reftime = evdata.GetData(Decoder::kPulseTime, d->crate, d->slot, d->refchan, 0);
+	    rawhit->SetReference(signal, reftime);
+	  } else {
+	    cout << "HitList(event=" << evdata.GetEvNum() << "): refchan " << d->refchan <<
+	      " missing for (" << d->crate << ", " << d->slot <<
+	      ", " << chan << ")" << endl;
+	  }
+	} else {
+	  if(d->refindex >=0 && d->refindex < fNRefIndex) {
+	    if(fRefIndexMaps[d->refindex].hashit) {
+	      rawhit->SetReference(signal, fRefIndexMaps[d->refindex].reftime);
+	    } else {
+	      cout << "HitList(event=" << evdata.GetEvNum() << "): refindex " << d->refindex <<
+          " (" << fRefIndexMaps[d->refindex].crate <<
+          ", " << fRefIndexMaps[d->refindex].slot <<
+          ", " << fRefIndexMaps[d->refindex].channel << ")" <<
+		" missing for (" << d->crate << ", " << d->slot <<
+		", " << chan << ")" << endl;
+	    }
+	  }
+	}
       }
     }
   }
diff --git a/src/THcRawAdcHit.cxx b/src/THcRawAdcHit.cxx
index 5377003..2f82b0c 100644
--- a/src/THcRawAdcHit.cxx
+++ b/src/THcRawAdcHit.cxx
@@ -56,6 +56,12 @@ Should be used for old style ADCs.
 Should be used for flash 250 modules.
 */
 
+/**
+\fn void THcRawAdcHit::SetRefTime(Int_t refTime)
+\brief Sets reference time. In channels.
+\param[in] refTime Reference time. In channels.
+*/
+
 /**
 \fn Int_t THcRawAdcHit::GetRawData(UInt_t iPulse=0) const
 \brief Gets raw pulse integral. In channels.
@@ -193,7 +199,7 @@ THcRawAdcHit::THcRawAdcHit() :
   fPeakPedestalRatio(1.0*fNPeakSamples/fNPedestalSamples),
   fSubsampleToTimeFactor(0.0625),
   fPed(0), fPulseInt(), fPulseAmp(), fPulseTime(), fSample(),
-  fHasMulti(kFALSE), fNPulses(0), fNSamples(0)
+  fRefTime(0), fHasMulti(kFALSE), fHasRefTime(kFALSE), fNPulses(0), fNSamples(0)
 {}
 
 THcRawAdcHit& THcRawAdcHit::operator=(const THcRawAdcHit& right) {
@@ -212,6 +218,8 @@ THcRawAdcHit& THcRawAdcHit::operator=(const THcRawAdcHit& right) {
     fHasMulti = right.fHasMulti;
     fNPulses  = right.fNPulses;
     fNSamples = right.fNSamples;
+    fRefTime = right.fRefTime;
+    fHasRefTime = right.fHasRefTime;
   }
 
   return *this;
@@ -234,6 +242,8 @@ void THcRawAdcHit::Clear(Option_t* opt) {
   fHasMulti = kFALSE;
   fNPulses = 0;
   fNSamples = 0;
+  fRefTime = 0;
+  fHasRefTime = kFALSE;
 }
 
 void THcRawAdcHit::SetData(Int_t data) {
@@ -246,6 +256,11 @@ void THcRawAdcHit::SetData(Int_t data) {
   ++fNPulses;
 }
 
+void THcRawAdcHit::SetRefTime(Int_t refTime) {
+  fRefTime = refTime;
+  fHasRefTime = kTRUE;
+}
+
 void THcRawAdcHit::SetSample(Int_t data) {
   if (fNSamples >= fMaxNSamples) {
     throw std::out_of_range(
@@ -419,7 +434,11 @@ Double_t THcRawAdcHit::GetPulseAmp(UInt_t iPulse) const {
 }
 
 Double_t THcRawAdcHit::GetPulseTime(UInt_t iPulse) const {
-  return (static_cast<Double_t>(fPulseTime[iPulse])*GetAdcTons());
+  Int_t rawtime = fPulseTime[iPulse];
+  if (fHasRefTime) {
+    rawtime -= fRefTime;
+  }
+  return (static_cast<Double_t>(rawtime)*GetAdcTons());
 }
 
 Int_t THcRawAdcHit::GetSampleIntRaw() const {
@@ -467,4 +486,21 @@ Double_t THcRawAdcHit::GetAdcTons() const {
   return fAdcTimeRes;
 }
 
+Int_t THcRawAdcHit::GetRefTime() const {
+  if (fHasRefTime) {
+    return fRefTime;
+  }
+  else {
+    TString msg = TString::Format(
+      "`THcRawAdcHit::GetRefTime`: Reference time not available!"
+    );
+    throw std::runtime_error(msg.Data());
+  }
+}
+
+
+Bool_t THcRawAdcHit::HasRefTime() const {
+  return fHasRefTime;
+}
+
 ClassImp(THcRawAdcHit)
diff --git a/src/THcRawAdcHit.h b/src/THcRawAdcHit.h
index 6dc9ad6..4663e12 100644
--- a/src/THcRawAdcHit.h
+++ b/src/THcRawAdcHit.h
@@ -14,6 +14,7 @@ class THcRawAdcHit : public TObject {
 
     void SetData(Int_t data);
     void SetSample(Int_t data);
+    void SetRefTime(Int_t refTime);
     void SetDataTimePedestalPeak(
       Int_t data, Int_t time, Int_t pedestal, Int_t peak
     );
@@ -31,12 +32,14 @@ class THcRawAdcHit : public TObject {
     UInt_t GetNSamples() const;
 
     Bool_t HasMulti() const;
+    Bool_t HasRefTime() const;
 
     Int_t GetPedRaw() const;
     Int_t GetPulseIntRaw(UInt_t iPulse=0) const;
     Int_t GetPulseAmpRaw(UInt_t iPulse=0) const;
     Int_t GetPulseTimeRaw(UInt_t iPulse=0) const;
     Int_t GetSampleRaw(UInt_t iSample=0) const;
+    Int_t GetRefTime() const;
 
     Double_t GetPed() const;
     Double_t GetPulseInt(UInt_t iPulse=0) const;
@@ -73,8 +76,10 @@ class THcRawAdcHit : public TObject {
     Int_t fPulseAmp[fMaxNPulses];
     Int_t fPulseTime[fMaxNPulses];
     Int_t fSample[fMaxNSamples];
+    Int_t fRefTime;
 
     Bool_t fHasMulti;
+    Bool_t fHasRefTime;
     UInt_t fNPulses;
     UInt_t fNSamples;
 
diff --git a/src/THcRawHodoHit.cxx b/src/THcRawHodoHit.cxx
index db2d487..2e7c84c 100644
--- a/src/THcRawHodoHit.cxx
+++ b/src/THcRawHodoHit.cxx
@@ -94,10 +94,11 @@ void THcRawHodoHit::SetDataTimePedestalPeak(
 
 
 void THcRawHodoHit::SetReference(Int_t signal, Int_t reference) {
-  if (fNAdcSignals <= signal && signal < fNAdcSignals+fNTdcSignals) {
+  if (signal < fNAdcSignals) {
+    fAdcHits[signal].SetRefTime(reference);
+  } else if (signal < fNAdcSignals+fNTdcSignals) {
     fTdcHits[signal-fNAdcSignals].SetRefTime(reference);
-  }
-  else {
+  } else {
     throw std::out_of_range(
       "`THcRawHodoHit::SetReference`: only signals `2` and `3` available!"
     );
-- 
GitLab