From 954cff30202cbc4f698938057c0ca19c6937f888 Mon Sep 17 00:00:00 2001
From: "Stephen A. Wood" <saw@jlab.org>
Date: Tue, 1 May 2012 15:19:49 -0400
Subject: [PATCH] Add some compatibility code for older root versions that
 don't have the TClonesArray ConstructedAt method.

Raw hit class for drift chambers and skeleton drift chamber that prints
out drift chamber package hits.

Move Compare method from THcHodoscopeHit to ThcRawHit since it should
work for any derived class.

Get detector name -> ID mapping from the map file comments
---
 Makefile                |   3 +-
 src/HallC_LinkDef.h     |   2 +
 src/THcDCHit.cxx        |  78 +++++++++++
 src/THcDCHit.h          |  37 +++++
 src/THcDetectorMap.cxx  |  55 +++++---
 src/THcDetectorMap.h    |   7 +
 src/THcDriftChamber.cxx | 297 ++++++++++++++++++++++++++++++++++++++++
 src/THcDriftChamber.h   |  79 +++++++++++
 src/THcHitList.cxx      |  10 ++
 src/THcHodoscope.cxx    |   2 +-
 src/THcHodoscopeHit.cxx |   2 +
 src/THcHodoscopeHit.h   |   4 +-
 src/THcRawHit.cxx       |  21 +++
 src/THcRawHit.h         |   6 +-
 14 files changed, 576 insertions(+), 27 deletions(-)
 create mode 100644 src/THcDCHit.cxx
 create mode 100644 src/THcDCHit.h
 create mode 100644 src/THcDriftChamber.cxx
 create mode 100644 src/THcDriftChamber.h

diff --git a/Makefile b/Makefile
index 6fc33b4..ebcb3cd 100644
--- a/Makefile
+++ b/Makefile
@@ -10,8 +10,9 @@
 
 SRC  =  src/THcInterface.cxx src/THcParmList.cxx src/THcAnalyzer.cxx \
 	src/THcHodoscopeHit.cxx src/THcRawHit.cxx \
+	src/THcDCHit.cxx \
 	src/THcHitList.cxx src/THcDetectorMap.cxx src/THcHodoscope.cxx \
-	src/THcHallCSpectrometer.cxx
+	src/THcHallCSpectrometer.cxx src/THcDriftChamber.cxx
 
 # Name of your package. 
 # The shared library that will be built will get the name lib$(PACKAGE).so
diff --git a/src/HallC_LinkDef.h b/src/HallC_LinkDef.h
index c743ba4..5ac786e 100644
--- a/src/HallC_LinkDef.h
+++ b/src/HallC_LinkDef.h
@@ -12,8 +12,10 @@
 #pragma link C++ class THcAnalyzer+;
 #pragma link C++ class THcRawHit+;
 #pragma link C++ class THcHodoscopeHit+;
+#pragma link C++ class THcDCHit+;
 #pragma link C++ class THcHitList+;
 #pragma link C++ class THcHodoscope+;
+#pragma link C++ class THcDriftChamber+;
 #pragma link C++ class THcDetectorMap+;
 #pragma link C++ class THcHallCSpectrometer+;
 
diff --git a/src/THcDCHit.cxx b/src/THcDCHit.cxx
new file mode 100644
index 0000000..261245a
--- /dev/null
+++ b/src/THcDCHit.cxx
@@ -0,0 +1,78 @@
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// THcDCHit                                                                  //
+//                                                                           //
+// Class representing for drift chamber wire (or other device with           //
+//   a single multihit TDC channel per detector element                      //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+#include "THcDCHit.h"
+
+using namespace std;
+
+
+void THcDCHit::SetData(Int_t signal, Int_t data) {
+  fTDC[fNHits++] = data;
+}
+
+// Return just the first hit
+Int_t THcDCHit::GetData(Int_t signal) {
+  if(fNHits>0) {
+    return(fTDC[0]);
+  } else {
+    return(-1);
+  }
+}
+
+// Return a requested hit
+Int_t THcDCHit::GetData(Int_t signal, Int_t ihit) {
+  if(ihit >=0 && ihit< fNHits) {
+    return(fTDC[ihit]);
+  } else {
+    return(-1);
+  }
+}
+
+
+Int_t THcDCHit::Compare(const TObject* obj) const
+{
+  // Compare to sort by plane and counter
+  // Should we be able to move this into THcRawHit
+
+  const THcDCHit* hit = dynamic_cast<const THcDCHit*>(obj);
+
+  if(!hit) return -1;
+  Int_t p1 = fPlane;
+  Int_t p2 = hit->fPlane;
+  if(p1 < p2) return -1;
+  else if(p1 > p2) return 1;
+  else {
+    Int_t c1 = fCounter;
+    Int_t c2 = hit->fCounter;
+    if(c1 < c2) return -1;
+    else if (c1 == c2) return 0;
+    else return 1;
+  }
+}
+//_____________________________________________________________________________
+THcDCHit& THcDCHit::operator=( const THcDCHit& rhs )
+{
+  // Assignment operator.
+
+  THcRawHit::operator=(rhs);
+  if ( this != &rhs ) {
+    fPlane = rhs.fPlane;
+    fCounter = rhs.fCounter;
+    fNHits = rhs.fNHits;
+    for(Int_t ihit=0;ihit<fNHits;ihit++) {
+      fTDC[ihit] = rhs.fTDC[ihit];
+    }
+  }
+  return *this;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+ClassImp(THcDCHit)
+
diff --git a/src/THcDCHit.h b/src/THcDCHit.h
new file mode 100644
index 0000000..5523c79
--- /dev/null
+++ b/src/THcDCHit.h
@@ -0,0 +1,37 @@
+#ifndef ROOT_THcDCHit
+#define ROOT_THcDCHit
+
+#include "THcRawHit.h"
+
+#define MAXHITS 16
+
+class THcDCHit : public THcRawHit {
+
+ public:
+
+ THcDCHit(Int_t plane=0, Int_t counter=0) : THcRawHit(plane, counter), 
+    fNHits(0) {
+  }
+  THcDCHit& operator=( const THcDCHit& );
+  virtual ~THcDCHit() {}
+
+  virtual void Clear( Option_t* opt="" ) { fNHits=0; }
+
+  void SetData(Int_t signal, Int_t data);
+  Int_t GetData(Int_t signal);
+  Int_t GetData(Int_t signal, Int_t ihit);
+
+  virtual Bool_t  IsSortable () const {return kTRUE; }
+  virtual Int_t   Compare(const TObject* obj) const;
+
+  Int_t fNHits;
+  Int_t fTDC[MAXHITS];
+
+ protected:
+
+ private:
+
+  ClassDef(THcDCHit, 0);	// DC hit class
+};  
+
+#endif
diff --git a/src/THcDetectorMap.cxx b/src/THcDetectorMap.cxx
index 5a9214f..24ba354 100644
--- a/src/THcDetectorMap.cxx
+++ b/src/THcDetectorMap.cxx
@@ -33,7 +33,7 @@ inline static bool IsComment( const string& s, string::size_type pos )
 }
 
 //_____________________________________________________________________________
-THcDetectorMap::THcDetectorMap() : fNchans(0)
+THcDetectorMap::THcDetectorMap() : fNchans(0), fNIDs(0)
 {
 }
 
@@ -64,25 +64,18 @@ Int_t THcDetectorMap::FillMap(THaDetMap *detmap, const char *detectorname)
   // Translate detector name into and ID
   // For now just long if then else.  Could get it from the comments
   // at the beginning of the map file.
-  Int_t did;
-  if(strcasecmp(detectorname,"HDC")==0) {
-    did = 1;
-  } else if (strcasecmp(detectorname,"HSCIN")==0) {
-    did = 2;
-  } else if (strcasecmp(detectorname,"HCER")==0) {
-    did = 3;
-  } else if (strcasecmp(detectorname,"HCAL")==0) {
-    did = 4;
-  } else if (strcasecmp(detectorname,"HMISC")==0) {
-    did = 5;
-  } else if (strcasecmp(detectorname,"GMISC")==0) {
-    did = 6;
-  } else if (strcasecmp(detectorname,"HAERO")==0) {
-    did = 7;
-  } else {
+  Int_t did=-1;
+  for(Int_t i=0; i < fNIDs; i++) {
+    if(strcasecmp(detectorname,fIDMap[i].name) == 0) {
+      did = fIDMap[i].id;
+      break;
+    }
+  }
+  if(did < 0) {
+    cout << "FillMap Error: No detector ID registered for " << detectorname << endl;
+    cout << "     Using detector id of 0" << endl;
     did = 0;
   }
-  // Start SHMS with S?  What about SOS?
 
   mlist.clear();
   //  cout << "fNchans=" << fNchans << endl;
@@ -207,10 +200,24 @@ void THcDetectorMap::Load(const char *fname)
 
   while(getline(ifile,line)) {
     // BLank line or comment
-    if(line.empty()
-       || (start = line.find_first_not_of( whtspc )) == string::npos
-       || IsComment(line, start) )
+    if(line.empty()) continue;
+    if((start = line.find_first_not_of( whtspc )) == string::npos) continue;
+    if(IsComment(line, start)) { // Check for ID assignments
+      // Get rid of all white space
+      while((pos=line.find_first_of(whtspc)) != string::npos) {
+	line.erase(pos,1);
+      }
+      line.erase(0,1);	// Erase "!"
+      if(! ((pos=line.find("_ID=")) == string::npos)) {
+	fIDMap[fNIDs].name = new char [pos+1];
+	strncpy(fIDMap[fNIDs].name,line.c_str(),pos);
+	fIDMap[fNIDs].name[pos] = '\0';
+	start = (pos += 4); // Move to after "="
+	while(isdigit(line.at(pos++)));
+	fIDMap[fNIDs++].id = atoi(line.substr(start,pos).c_str());
+      }
       continue;
+    }
 
     //    cout << "MAPA: " << line << endl;
 
@@ -294,6 +301,12 @@ void THcDetectorMap::Load(const char *fname)
       fNchans++;
     }
   }
+  cout << endl << "   Detector ID Map" << endl << endl;
+  for(Int_t i=0; i < fNIDs; i++) {
+    cout << i << " ";
+    cout << fIDMap[i].name << " " << fIDMap[i].id << endl;
+  }
+  cout << endl;
 
 }
 
diff --git a/src/THcDetectorMap.h b/src/THcDetectorMap.h
index d78df90..1dd95b2 100644
--- a/src/THcDetectorMap.h
+++ b/src/THcDetectorMap.h
@@ -49,6 +49,13 @@ class THcDetectorMap : public TObject {
   };
   std::list<ModChanList> mlist;
 
+  struct IDMap {
+    char* name;
+    Int_t id;
+  };
+  IDMap fIDMap[50];
+  Int_t fNIDs;			/* Number of detector IDs */
+
   bool compare(const ChaninMod *first, const ChaninMod *second);
 
  protected:
diff --git a/src/THcDriftChamber.cxx b/src/THcDriftChamber.cxx
new file mode 100644
index 0000000..2e8881d
--- /dev/null
+++ b/src/THcDriftChamber.cxx
@@ -0,0 +1,297 @@
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// THcDriftChamber                                                              //
+//                                                                           //
+// Class for a generic hodoscope consisting of multiple                      //
+// planes with multiple paddles with phototubes on both ends.                //
+// This differs from Hall A scintillator class in that it is the whole       //
+// hodoscope array, not just one plane.                                      //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+#include "THcDriftChamber.h"
+#include "THaEvData.h"
+#include "THaDetMap.h"
+#include "THcDetectorMap.h"
+#include "THcGlobals.h"
+#include "THcParmList.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;
+
+//_____________________________________________________________________________
+THcDriftChamber::THcDriftChamber( const char* name, const char* description,
+				  THaApparatus* apparatus ) :
+  THaNonTrackingDetector(name,description,apparatus)
+{
+  // Constructor
+
+  fTrackProj = new TClonesArray( "THaTrackProj", 5 );
+}
+
+//_____________________________________________________________________________
+THcDriftChamber::THcDriftChamber( ) :
+  THaNonTrackingDetector()
+{
+  // Constructor
+}
+
+//_____________________________________________________________________________
+THaAnalysisObject::EStatus THcDriftChamber::Init( const TDatime& date )
+{
+  static const char* const here = "Init()";
+
+  if( THaNonTrackingDetector::Init( date ) )
+    return fStatus;
+
+  // Replace with what we need for Hall C
+  //  const DataDest tmp[NDEST] = {
+  //    { &fRTNhit, &fRANhit, fRT, fRT_c, fRA, fRA_p, fRA_c, fROff, fRPed, fRGain },
+  //    { &fLTNhit, &fLANhit, fLT, fLT_c, fLA, fLA_p, fLA_c, fLOff, fLPed, fLGain }
+  //  };
+  //  memcpy( fDataDest, tmp, NDEST*sizeof(DataDest) );
+
+  // Should probably put this in ReadDatabase as we will know the
+  // maximum number of hits after setting up the detector map
+
+  THcHitList::InitHitList(fDetMap, "THcDCHit", 1000);
+
+  // Will need to determine which apparatus it belongs to and use the
+  // appropriate detector ID in the FillMap call
+  if( gHcDetectorMap->FillMap(fDetMap, "HDC") < 0 ) {
+    Error( Here(here), "Error filling detectormap for %s.", 
+	     "HSCIN");
+      return kInitError;
+  }
+
+  return fStatus = kOK;
+}
+
+//_____________________________________________________________________________
+Int_t THcDriftChamber::ReadDatabase( const TDatime& date )
+{
+  // Read this detector's parameters from the database file 'fi'.
+  // This function is called by THaDetectorBase::Init() once at the
+  // beginning of the analysis.
+  // 'date' contains the date/time of the run being analyzed.
+
+  //  static const char* const here = "ReadDatabase()";
+
+  // Read data from database 
+  // Pull values from the THcParmList instead of reading a database
+  // file like Hall A does.
+
+  //  DBRequest list[] = {
+  //    { "TDC_offsetsL", fLOff, kDouble, fNelem },
+  //    { "TDC_offsetsR", fROff, kDouble, fNelem },
+  //    { "ADC_pedsL", fLPed, kDouble, fNelem },
+  //    { "ADC_pedsR", fRPed, kDouble, fNelem },
+  //    { "ADC_coefL", fLGain, kDouble, fNelem },
+  //    { "ADC_coefR", fRGain, kDouble, fNelem },
+  //    { "TDC_res",   &fTdc2T },
+  //    { "TransSpd",  &fCn },
+  //    { "AdcMIP",    &fAdcMIP },
+  //    { "NTWalk",    &fNTWalkPar, kInt },
+  //    { "Timewalk",  fTWalkPar, kDouble, 2*fNelem },
+  //    { "ReTimeOff", fTrigOff, kDouble, fNelem },
+  //    { "AvgRes",    &fResolution },
+  //    { "Atten",     &fAttenuation },
+  //    { 0 }
+  //  };
+
+  // We will probably want to add some kind of method to gHcParms to allow
+  // bulk retrieval of parameters of interest.
+
+  // Will need to determine which spectrometer in order to construct
+  // the parameter names (e.g. hscin_1x_nr vs. sscin_1x_nr)
+
+  fNPlanes = *(Int_t *)gHcParms->Find("hdc_num_planes")->GetValuePointer();
+
+  fNWires = new Int_t [fNPlanes];
+  Int_t* p= (Int_t *)gHcParms->Find("hdc_nrwire")->GetValuePointer();
+  for(Int_t i=0;i<fNPlanes;i++) {
+    fNWires[i] = p[i];
+  }
+
+  fIsInit = true;
+
+  return kOK;
+}
+
+//_____________________________________________________________________________
+Int_t THcDriftChamber::DefineVariables( EMode mode )
+{
+  // Initialize global variables and lookup table for decoder
+
+  if( mode == kDefine && fIsSetup ) return kOK;
+  fIsSetup = ( mode == kDefine );
+
+  // Register variables in global list
+
+  //  RVarDef vars[] = {
+  //    { "nlthit", "Number of Left paddles TDC times",  "fLTNhit" },
+  //    { "nrthit", "Number of Right paddles TDC times", "fRTNhit" },
+  //    { "nlahit", "Number of Left paddles ADCs amps",  "fLANhit" },
+  //    { "nrahit", "Number of Right paddles ADCs amps", "fRANhit" },
+  //    { "lt",     "TDC values left side",              "fLT" },
+  //    { "lt_c",   "Corrected times left side",         "fLT_c" },
+  //    { "rt",     "TDC values right side",             "fRT" },
+  //    { "rt_c",   "Corrected times right side",        "fRT_c" },
+  //    { "la",     "ADC values left side",              "fLA" },
+  //    { "la_p",   "Corrected ADC values left side",    "fLA_p" },
+  //    { "la_c",   "Corrected ADC values left side",    "fLA_c" },
+  //    { "ra",     "ADC values right side",             "fRA" },
+  //    { "ra_p",   "Corrected ADC values right side",   "fRA_p" },
+  //    { "ra_c",   "Corrected ADC values right side",   "fRA_c" },
+  //    { "nthit",  "Number of paddles with l&r TDCs",   "fNhit" },
+  //    { "t_pads", "Paddles with l&r coincidence TDCs", "fHitPad" },
+  //    { "y_t",    "y-position from timing (m)",        "fYt" },
+  //    { "y_adc",  "y-position from amplitudes (m)",    "fYa" },
+  //    { "time",   "Time of hit at plane (s)",          "fTime" },
+  //    { "dtime",  "Est. uncertainty of time (s)",      "fdTime" },
+  //    { "dedx",   "dEdX-like deposited in paddle",     "fAmpl" },
+  //    { "troff",  "Trigger offset for paddles",        "fTrigOff"},
+  //    { "trn",    "Number of tracks for hits",         "GetNTracks()" },
+  //    { "trx",    "x-position of track in det plane",  "fTrackProj.THaTrackProj.fX" },
+  //    { "try",    "y-position of track in det plane",  "fTrackProj.THaTrackProj.fY" },
+  //    { "trpath", "TRCS pathlen of track to det plane","fTrackProj.THaTrackProj.fPathl" },
+  //    { "trdx",   "track deviation in x-position (m)", "fTrackProj.THaTrackProj.fdX" },
+  //    { "trpad",  "paddle-hit associated with track",  "fTrackProj.THaTrackProj.fChannel" },
+  //    { 0 }
+  //  };
+  //  return DefineVarsFromList( vars, mode );
+  return kOK;
+}
+
+//_____________________________________________________________________________
+THcDriftChamber::~THcDriftChamber()
+{
+  // Destructor. Remove variables from global list.
+
+  if( fIsSetup )
+    RemoveVariables();
+  if( fIsInit )
+    DeleteArrays();
+  if (fTrackProj) {
+    fTrackProj->Clear();
+    delete fTrackProj; fTrackProj = 0;
+  }
+}
+
+//_____________________________________________________________________________
+void THcDriftChamber::DeleteArrays()
+{
+  // Delete member arrays. Used by destructor.
+
+  delete [] fNWires;  fNWires = NULL;
+  //  delete [] fSpacing;  fSpacing = NULL;
+  //  delete [] fCenter;   fCenter = NULL; // This 2D. What is correct way to delete?
+
+  //  delete [] fRA_c;    fRA_c    = NULL;
+  //  delete [] fRA_p;    fRA_p    = NULL;
+  //  delete [] fRA;      fRA      = NULL;
+  //  delete [] fLA_c;    fLA_c    = NULL;
+  //  delete [] fLA_p;    fLA_p    = NULL;
+  //  delete [] fLA;      fLA      = NULL;
+  //  delete [] fRT_c;    fRT_c    = NULL;
+  //  delete [] fRT;      fRT      = NULL;
+  //  delete [] fLT_c;    fLT_c    = NULL;
+  //  delete [] fLT;      fLT      = NULL;
+  
+  //  delete [] fRGain;   fRGain   = NULL;
+  //  delete [] fLGain;   fLGain   = NULL;
+  //  delete [] fRPed;    fRPed    = NULL;
+  //  delete [] fLPed;    fLPed    = NULL;
+  //  delete [] fROff;    fROff    = NULL;
+  //  delete [] fLOff;    fLOff    = NULL;
+  //  delete [] fTWalkPar; fTWalkPar = NULL;
+  //  delete [] fTrigOff; fTrigOff = NULL;
+
+  //  delete [] fHitPad;  fHitPad  = NULL;
+  //  delete [] fTime;    fTime    = NULL;
+  //  delete [] fdTime;   fdTime   = NULL;
+  //  delete [] fYt;      fYt      = NULL;
+  //  delete [] fYa;      fYa      = NULL;
+}
+
+//_____________________________________________________________________________
+inline 
+void THcDriftChamber::ClearEvent()
+{
+  // Reset per-event data.
+
+  fTrackProj->Clear();
+}
+
+//_____________________________________________________________________________
+Int_t THcDriftChamber::Decode( const THaEvData& evdata )
+{
+
+  // Get the Hall C style hitlist (fRawHitList) for this event
+  Int_t nhits = THcHitList::DecodeToHitList(evdata);
+
+  // fRawHitList is TClones array of THcDCHit objects
+  for(Int_t ihit = 0; ihit < fNRawHits ; ihit++) {
+    THcDCHit* hit = (THcDCHit *) fRawHitList->At(ihit);
+    cout << ihit << " : " << hit->fPlane << ":" << hit->fCounter << " : "
+	 << endl;
+    for(Int_t imhit = 0; imhit < hit->fNHits; imhit++) {
+      cout << "                     " << imhit << " " << hit->fTDC[imhit]
+	   << endl;
+    }
+  }
+  cout << endl;
+
+  return nhits;
+}
+
+//_____________________________________________________________________________
+Int_t THcDriftChamber::ApplyCorrections( void )
+{
+  return(0);
+}
+
+//_____________________________________________________________________________
+Int_t THcDriftChamber::CoarseProcess( TClonesArray& /* tracks */ )
+{
+  // Calculation of coordinates of particle track cross point with scint
+  // plane in the detector coordinate system. For this, parameters of track 
+  // reconstructed in THaVDC::CoarseTrack() are used.
+  //
+  // Apply corrections and reconstruct the complete hits.
+  //
+  //  static const Double_t sqrt2 = TMath::Sqrt(2.);
+  
+  ApplyCorrections();
+
+  return 0;
+}
+
+//_____________________________________________________________________________
+Int_t THcDriftChamber::FineProcess( TClonesArray& tracks )
+{
+  // Reconstruct coordinates of particle track cross point with scintillator
+  // plane, and copy the data into the following local data structure:
+  //
+  // Units of measurements are meters.
+
+  // Calculation of coordinates of particle track cross point with scint
+  // plane in the detector coordinate system. For this, parameters of track 
+  // reconstructed in THaVDC::FineTrack() are used.
+
+  return 0;
+}
+
+ClassImp(THcDriftChamber)
+////////////////////////////////////////////////////////////////////////////////
diff --git a/src/THcDriftChamber.h b/src/THcDriftChamber.h
new file mode 100644
index 0000000..b9f7be4
--- /dev/null
+++ b/src/THcDriftChamber.h
@@ -0,0 +1,79 @@
+#ifndef ROOT_THcDriftChamber
+#define ROOT_THcDriftChamber
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// THcDriftChamber                                                           //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+#include "TClonesArray.h"
+#include "THaNonTrackingDetector.h"
+#include "THcHitList.h"
+#include "THcDCHit.h"
+
+class THaScCalib;
+
+class THcDriftChamber : public THaNonTrackingDetector, public THcHitList {
+
+public:
+  THcDriftChamber( const char* name, const char* description = "",
+		   THaApparatus* a = NULL );
+  virtual ~THcDriftChamber();
+
+  virtual Int_t      Decode( const THaEvData& );
+  virtual EStatus    Init( const TDatime& run_time );
+  virtual Int_t      CoarseProcess( TClonesArray& tracks );
+  virtual Int_t      FineProcess( TClonesArray& tracks );
+  
+  virtual Int_t      ApplyCorrections( void );
+
+  //  Int_t GetNHits() const { return fNhit; }
+  
+  Int_t GetNTracks() const { return fTrackProj->GetLast()+1; }
+  const TClonesArray* GetTrackHits() const { return fTrackProj; }
+  
+  friend class THaScCalib;
+
+  THcDriftChamber();  // for ROOT I/O
+protected:
+
+  // Calibration
+
+  // Per-event data
+
+
+  // Potential Hall C parameters.  Mostly here for demonstration
+  Int_t fNPlanes;
+  Int_t* fNWires;		// Number of wires per plane
+
+  TClonesArray*  fTrackProj;  // projection of track onto scintillator plane
+                              // and estimated match to TOF paddle
+  // Useful derived quantities
+  // double tan_angle, sin_angle, cos_angle;
+  
+  //  static const char NDEST = 2;
+  //  struct DataDest {
+  //    Int_t*    nthit;
+  //    Int_t*    nahit;
+  //    Double_t*  tdc;
+  //    Double_t*  tdc_c;
+  //    Double_t*  adc;
+  //    Double_t*  adc_p;
+  //    Double_t*  adc_c;
+  //    Double_t*  offset;
+  //    Double_t*  ped;
+  //    Double_t*  gain;
+  //  } fDataDest[NDEST];     // Lookup table for decoder
+
+  void           ClearEvent();
+  void           DeleteArrays();
+  virtual Int_t  ReadDatabase( const TDatime& date );
+  virtual Int_t  DefineVariables( EMode mode = kDefine );
+
+  ClassDef(THcDriftChamber,0)   // Generic hodoscope class
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/src/THcHitList.cxx b/src/THcHitList.cxx
index 9a1303b..81464d6 100644
--- a/src/THcHitList.cxx
+++ b/src/THcHitList.cxx
@@ -11,6 +11,8 @@
 //////////////////////////////////////////////////////////////////////////
 
 #include "THcHitList.h"
+#include "TError.h"
+#include "TClass.h"
 
 using namespace std;
 
@@ -35,7 +37,15 @@ void THcHitList::InitHitList(THaDetMap* detmap,
   fNMaxRawHits = maxhits;
   fNRawHits = 0;
   for(Int_t i=0;i<maxhits;i++) {
+#if ROOT_VERSION_CODE >= ROOT_VERSION(5,32,0)
     fRawHitList->ConstructedAt(i);
+#else
+  // The essence of the ConstructedAt code explictly
+    TObject* obj = (*fRawHitList)[i];
+    R__ASSERT( obj );  // should never happen ...
+    if( !obj->TestBit(TObject::kNotDeleted) )
+      fRawHitClass->New(obj);
+#endif
   }
   
   fdMap = detmap;
diff --git a/src/THcHodoscope.cxx b/src/THcHodoscope.cxx
index ede9289..b70ac6c 100644
--- a/src/THcHodoscope.cxx
+++ b/src/THcHodoscope.cxx
@@ -71,7 +71,7 @@ THaAnalysisObject::EStatus THcHodoscope::Init( const TDatime& date )
   // appropriate detector ID in the FillMap call
   if( gHcDetectorMap->FillMap(fDetMap, "HSCIN") < 0 ) {
     Error( Here(here), "Error filling detectormap for %s.", 
-	     "detectorname");
+	     "HSCIN");
       return kInitError;
   }
 
diff --git a/src/THcHodoscopeHit.cxx b/src/THcHodoscopeHit.cxx
index 1a34c8b..9e3ea84 100644
--- a/src/THcHodoscopeHit.cxx
+++ b/src/THcHodoscopeHit.cxx
@@ -38,6 +38,7 @@ Int_t THcHodoscopeHit::GetData(Int_t signal) {
   return(-1); // Actually should throw exception
 }
 
+#if 0
 Int_t THcHodoscopeHit::Compare(const TObject* obj) const
 {
   // Compare to sort by plane and counter
@@ -57,6 +58,7 @@ Int_t THcHodoscopeHit::Compare(const TObject* obj) const
     else return 1;
   }
 }
+#endif
 //_____________________________________________________________________________
 THcHodoscopeHit& THcHodoscopeHit::operator=( const THcHodoscopeHit& rhs )
 {
diff --git a/src/THcHodoscopeHit.h b/src/THcHodoscopeHit.h
index f8ce97b..0bac2d1 100644
--- a/src/THcHodoscopeHit.h
+++ b/src/THcHodoscopeHit.h
@@ -20,8 +20,8 @@ class THcHodoscopeHit : public THcRawHit {
   void SetData(Int_t signal, Int_t data);
   Int_t GetData(Int_t signal);
 
-  virtual Bool_t  IsSortable () const {return kTRUE; }
-  virtual Int_t   Compare(const TObject* obj) const;
+  //  virtual Bool_t  IsSortable () const {return kTRUE; }
+  //  virtual Int_t   Compare(const TObject* obj) const;
 
   Int_t fADC_pos;
   Int_t fADC_neg;
diff --git a/src/THcRawHit.cxx b/src/THcRawHit.cxx
index daa5138..3e37972 100644
--- a/src/THcRawHit.cxx
+++ b/src/THcRawHit.cxx
@@ -13,6 +13,27 @@
 //THcRawHit::~THcRawHit()
 //{}
 
+Int_t THcRawHit::Compare(const TObject* obj) const
+{
+  // Compare to sort by plane and counter
+
+  const THcRawHit* hit = dynamic_cast<const THcRawHit*>(obj);
+
+  if(!hit) return -1;
+  Int_t p1 = fPlane;
+  Int_t p2 = hit->fPlane;
+  if(p1 < p2) return -1;
+  else if(p1 > p2) return 1;
+  else {
+    Int_t c1 = fCounter;
+    Int_t c2 = hit->fCounter;
+    if(c1 < c2) return -1;
+    else if (c1 == c2) return 0;
+    else return 1;
+  }
+}
+
+
 ClassImp(THcRawHit)
 
 //_____________________________________________________________________________
diff --git a/src/THcRawHit.h b/src/THcRawHit.h
index 921939e..7372463 100644
--- a/src/THcRawHit.h
+++ b/src/THcRawHit.h
@@ -29,8 +29,10 @@ public:
   virtual Int_t GetData(Int_t signal) {return 0;};
 
   // Derived objects must be sortable and supply Compare method
-  virtual Bool_t  IsSortable () const {return kFALSE; }
-  virtual Int_t   Compare(const TObject* obj) const {return 0;}
+  //  virtual Bool_t  IsSortable () const {return kFALSE; }
+  //  virtual Int_t   Compare(const TObject* obj) const {return 0;}
+  virtual Bool_t  IsSortable () const {return kTRUE; }
+  virtual Int_t   Compare(const TObject* obj) const;
 
   Int_t fPlane;
   Int_t fCounter;
-- 
GitLab