diff --git a/Makefile b/Makefile
index f6ac9270e73a405a6765bbbdae0151b999060ef0..7beaa8b491cce123a2643c45c1a662737ed4ef07 100644
--- a/Makefile
+++ b/Makefile
@@ -10,7 +10,9 @@
 
 SRC  =  src/THcInterface.cxx src/THcParmList.cxx src/THcAnalyzer.cxx \
 	src/THcHodoscopeHit.cxx src/THcRawHit.cxx \
-	src/THcDetectorBase.cxx src/THcDetector.cxx
+	src/THcDetectorBase.cxx src/THcDetector.cxx \
+	src/THcSpectrometerDetector.cxx src/THcNonTrackingDetector.cxx \
+	src/THcHodoscope.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 fe969aba42679a86b3b72b1d4d35fc7f2c7234a3..c98a7cc684580db3083a281509a8d949c2c0d089 100644
--- a/src/HallC_LinkDef.h
+++ b/src/HallC_LinkDef.h
@@ -13,5 +13,8 @@
 #pragma link C++ class THcHodoscopeHit+;
 #pragma link C++ class THcDetectorBase+;
 #pragma link C++ class THcDetector+;
+#pragma link C++ class THcSpectrometerDetector+;
+#pragma link C++ class THcNonTrackingDetector+;
+#pragma link C++ class THcHodoscope+;
 
 #endif
diff --git a/src/THcHodoscope.cxx b/src/THcHodoscope.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..3f1029026afedf6964d1be273da4ed920a5990b3
--- /dev/null
+++ b/src/THcHodoscope.cxx
@@ -0,0 +1,703 @@
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// THcHodoscope
+//                                                                           //
+// Class for a generic hodoscope consisting of multiple                      //
+// planes with multiple paddles with phototubes on both ends.                //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+#include "THcHodoscope.h"
+#include "THaEvData.h"
+#include "THaDetMap.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;
+
+//_____________________________________________________________________________
+THcHodoscope::THcHodoscope( const char* name, const char* description,
+				  THaApparatus* apparatus ) :
+  THaNonTrackingDetector(name,description,apparatus)
+{
+  // Constructor
+  fTWalkPar = 0;
+
+  fTrackProj = new TClonesArray( "THaTrackProj", 5 );
+}
+
+//_____________________________________________________________________________
+THcHodoscope::THcHodoscope( ) :
+  THaNonTrackingDetector()
+{
+  // Constructor
+  fTWalkPar = NULL;
+  fTrackProj = NULL;
+  fRA_c = fRA_p = fRA = fLA_c = fLA_p = fLA = NULL;
+  fRT_c = fRT = fLT_c = fLT = NULL;
+  fRGain = fLGain = fRPed = fLPed = fROff = fLOff = NULL;
+  fTrigOff = fTime = fdTime = fYt = fYa = NULL;
+  fHitPad = NULL;
+}
+
+//_____________________________________________________________________________
+THaAnalysisObject::EStatus THcHodoscope::Init( const TDatime& date )
+{
+  // Extra initialization for scintillators: set up DataDest map
+
+  if( THaNonTrackingDetector::Init( date ) )
+    return fStatus;
+
+  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) );
+
+  return fStatus = kOK;
+}
+
+//_____________________________________________________________________________
+Int_t THcHodoscope::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()";
+  const int LEN = 200;
+  char buf[LEN];
+  Int_t nelem;
+
+  // Read data from database 
+  FILE* fi = OpenFile( date );
+  if( !fi ) return kFileError;
+
+  while ( ReadComment( fi, buf, LEN ) ) {}
+  fscanf ( fi, "%d", &nelem );                        // Number of  paddles
+  fgets ( buf, LEN, fi );
+
+  // Reinitialization only possible for same basic configuration 
+  if( fIsInit && nelem != fNelem ) {
+    Error( Here(here), "Cannot re-initalize with different number of paddles. "
+	   "(was: %d, now: %d). Detector not re-initialized.", fNelem, nelem );
+    fclose(fi);
+    return kInitError;
+  }
+  fNelem = nelem;
+
+  // Read detector map. Unless a model-number is given
+  // for the detector type, this assumes that the first half of the entries 
+  // are for ADCs and the second half, for TDCs.
+  while ( ReadComment( fi, buf, LEN ) ) {}
+  int i = 0;
+  fDetMap->Clear();
+  while (1) {
+    int pos;
+    Int_t first_chan, model;
+    Int_t crate, slot, first, last;
+    fgets ( buf, LEN, fi );
+    sscanf( buf, "%d%d%d%d%d%n", &crate, &slot, &first, &last, &first_chan, &pos );
+    if( crate < 0 ) break;
+    model=atoi(buf+pos); // if there is no model number given, set to zero
+    
+    if( fDetMap->AddModule( crate, slot, first, last, first_chan, model ) < 0 ) {
+      Error( Here(here), "Too many DetMap modules (maximum allowed - %d).", 
+	     THaDetMap::kDetMapSize);
+      fclose(fi);
+      return kInitError;
+    }
+  }
+  while ( ReadComment( fi, buf, LEN ) ) {}
+
+  Float_t x,y,z;
+  fscanf ( fi, "%f%f%f", &x, &y, &z );             // Detector's X,Y,Z coord
+  fgets ( buf, LEN, fi );
+  fOrigin.SetXYZ( x, y, z );
+  fgets ( buf, LEN, fi );
+  while ( ReadComment( fi, buf, LEN ) ) {}
+  fscanf ( fi, "%f%f%f", fSize, fSize+1, fSize+2 ); // Sizes of det on X,Y,Z
+  fgets ( buf, LEN, fi );
+  while ( ReadComment( fi, buf, LEN ) ) {}
+
+  Float_t angle;
+  fscanf ( fi, "%f", &angle );                     // Rotation angle of detector
+  fgets ( buf, LEN, fi );
+  const Float_t degrad = TMath::Pi()/180.0;
+  tan_angle = TMath::Tan(angle*degrad);
+  sin_angle = TMath::Sin(angle*degrad);
+  cos_angle = TMath::Cos(angle*degrad);
+
+  DefineAxes(angle*degrad);
+
+  // Dimension arrays
+  if( !fIsInit ) {
+    // Calibration data
+    fLOff  = new Double_t[ fNelem ];
+    fROff  = new Double_t[ fNelem ];
+    fLPed  = new Double_t[ fNelem ];
+    fRPed  = new Double_t[ fNelem ];
+    fLGain = new Double_t[ fNelem ];
+    fRGain = new Double_t[ fNelem ];
+
+    fTrigOff = new Double_t[ fNelem ];
+
+    // Per-event data
+    fLT   = new Double_t[ fNelem ];
+    fLT_c = new Double_t[ fNelem ];
+    fRT   = new Double_t[ fNelem ];
+    fRT_c = new Double_t[ fNelem ];
+    fLA   = new Double_t[ fNelem ];
+    fLA_p = new Double_t[ fNelem ];
+    fLA_c = new Double_t[ fNelem ];
+    fRA   = new Double_t[ fNelem ];
+    fRA_p = new Double_t[ fNelem ];
+    fRA_c = new Double_t[ fNelem ];
+
+    fNTWalkPar = 2*fNelem; // 1 paramter per paddle
+    fTWalkPar = new Double_t[ fNTWalkPar ];
+
+    fHitPad = new Int_t[ fNelem ];   
+    fTime   = new Double_t[ fNelem ]; // analysis indexed by paddle (yes, inefficient)
+    fdTime  = new Double_t[ fNelem ];
+    fAmpl   = new Double_t[ fNelem ];
+    
+    fYt     = new Double_t[ fNelem ];
+    fYa     = new Double_t[ fNelem ];
+    
+    fIsInit = true;
+  }
+  memset(fTrigOff,0,fNelem*sizeof(fTrigOff[0]));
+
+  // Set DEFAULT values here
+  // TDC resolution (s/channel)
+  fTdc2T = 0.1e-9;      // seconds/channel
+  fResolution = fTdc2T; // actual timing resolution 
+  // Speed of light in the scintillator material
+  fCn = 1.7e+8;    // meters/second
+  // Attenuation length
+  fAttenuation = 0.7; // inverse meters
+  // Time-walk correction parameters
+  fAdcMIP = 1.e10;    // large number for offset, so reference is effectively disabled
+  // timewalk coefficients for tw = coeff*(1./sqrt(ADC-Ped)-1./sqrt(ADCMip))
+  for (int i=0; i<fNTWalkPar; i++) fTWalkPar[i]=0;
+  // trigger-timing offsets (s)
+  for (int i=0; i<fNelem; i++) fTrigOff[i]=0;
+  
+  
+  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 }
+  };
+
+#if 0
+  if ( gHaDB && gHaDB->LoadValues(GetPrefix(),list,date) ) {
+    goto exit;  // the new database existed -- we're finished
+  }
+#endif
+  
+  // otherwise, gHaDB is unavailable, use the old file database
+  
+  // Read in the timing/adc calibration constants
+  // For fine-tuning of these data, we seek to a matching time stamp, or
+  // if no time stamp found, to a "configuration" section. Examples:
+  // 
+  // [ 2002-10-10 15:30:00 ]
+  // #comment line goes here
+  // <left TDC offsets>
+  // <right TDC offsets>
+  // <left ADC peds>
+  // <rigth ADC peds>
+  // <left ADC coeff>
+  // <right ADC coeff>
+  //
+  // if below aren't present, 'default' values are used
+  // <TDC resolution: seconds/channel>
+  // <speed-of-light in medium m/s>
+  // <attenuation length m^-1>
+  // <ADC of MIP>
+  // <number of timewalk parameters>
+  // <timewalk paramters>
+  //
+  //
+  // or
+  // 
+  // [ config=highmom ]
+  // comment line
+  // ...etc.
+  //
+  if( SeekDBdate( fi, date ) == 0 && fConfig.Length() > 0 && 
+      SeekDBconfig( fi, fConfig.Data() )) {}
+
+  while ( ReadComment( fi, buf, LEN ) ) {}
+  // Read calibration data
+  for (i=0;i<fNelem;i++) 
+    fscanf(fi,"%lf",fLOff+i);                    // Left Pads TDC offsets
+  fgets ( buf, LEN, fi );   // finish line
+  while ( ReadComment( fi, buf, LEN ) ) {}
+  for (i=0;i<fNelem;i++) 
+    fscanf(fi,"%lf",fROff+i);                    // Right Pads TDC offsets
+  fgets ( buf, LEN, fi );   // finish line
+  while ( ReadComment( fi, buf, LEN ) ) {}
+  for (i=0;i<fNelem;i++) 
+    fscanf(fi,"%lf",fLPed+i);                    // Left Pads ADC Pedest-s
+  fgets ( buf, LEN, fi );   // finish line, etc.
+  while ( ReadComment( fi, buf, LEN ) ) {}
+  for (i=0;i<fNelem;i++) 
+    fscanf(fi,"%lf",fRPed+i);                    // Right Pads ADC Pedes-s
+  fgets ( buf, LEN, fi );
+  while ( ReadComment( fi, buf, LEN ) ) {}
+  for (i=0;i<fNelem;i++) 
+    fscanf (fi,"%lf",fLGain+i);                  // Left Pads ADC Coeff-s
+  fgets ( buf, LEN, fi );
+  while ( ReadComment( fi, buf, LEN ) ) {}
+  for (i=0;i<fNelem;i++) 
+    fscanf (fi,"%lf",fRGain+i);                  // Right Pads ADC Coeff-s
+  fgets ( buf, LEN, fi ); 
+
+
+  while ( ReadComment( fi, buf, LEN ) ) {}
+  // Here on down, look ahead line-by-line
+  // stop reading if a '[' is found on a line (corresponding to the next date-tag)
+  // read in TDC resolution (s/channel)
+  if ( ! fgets(buf, LEN, fi) || strchr(buf,'[') ) goto exit;
+  sscanf(buf,"%lf",&fTdc2T);
+  fResolution = 3.*fTdc2T;      // guess at timing resolution
+
+  while ( ReadComment( fi, buf, LEN ) ) {}
+  // Speed of light in the scintillator material
+  if ( !fgets(buf, LEN, fi) ||  strchr(buf,'[') ) goto exit;
+  sscanf(buf,"%lf",&fCn);
+  
+  // Attenuation length (inverse meters)
+  while ( ReadComment( fi, buf, LEN ) ) {}
+  if ( !fgets ( buf, LEN, fi ) ||  strchr(buf,'[') ) goto exit;
+  sscanf(buf,"%lf",&fAttenuation);
+  
+  while ( ReadComment( fi, buf, LEN ) ) {}
+  // Time-walk correction parameters
+  if ( !fgets(buf, LEN, fi) ||  strchr(buf,'[') ) goto exit;
+  sscanf(buf,"%lf",&fAdcMIP);
+  
+  while ( ReadComment( fi, buf, LEN ) ) {}
+  // timewalk parameters
+  {
+    int cnt=0;
+    while ( cnt<fNTWalkPar && fgets( buf, LEN, fi ) && ! strchr(buf,'[') ) {
+      char *ptr = buf;
+      int pos=0;
+      while ( cnt < fNTWalkPar && sscanf(ptr,"%lf%n",&fTWalkPar[cnt],&pos)>0 ) {
+	ptr += pos;
+	cnt++;
+      }
+    }
+  }
+
+  while ( ReadComment( fi, buf, LEN ) ) {}
+  // trigger timing offsets
+  {
+    int cnt=0;
+    while ( cnt<fNelem && fgets( buf, LEN, fi ) && ! strchr(buf,'[') ) {
+      char *ptr = buf;
+      int pos=0;
+      while ( cnt < fNelem && sscanf(ptr,"%lf%n",&fTrigOff[cnt],&pos)>0 ) {
+	ptr += pos;
+	cnt++;
+      }
+    }
+  }
+  
+ exit:
+  fclose(fi);
+
+  if ( fDebug > 1 ) {
+    cout << '\n' << GetPrefix() << " calibration parameters: " << endl;;
+    for ( DBRequest *li = list; li->name; li++ ) {
+      cout << "  " << li->name;
+      int maxc = li->nelem;
+      if (maxc==0)maxc=1;
+      for (int i=0; i<maxc; i++) {
+	if (li->type==kDouble) cout << "  " << ((Double_t*)li->var)[i];
+	if (li->type==kInt) cout << "  " << ((Int_t*)li->var)[i];
+      }
+      cout << endl;
+    }
+  }
+  
+  return kOK;
+}
+
+//_____________________________________________________________________________
+Int_t THcHodoscope::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 );
+}
+
+//_____________________________________________________________________________
+THcHodoscope::~THcHodoscope()
+{
+  // Destructor. Remove variables from global list.
+
+  if( fIsSetup )
+    RemoveVariables();
+  if( fIsInit )
+    DeleteArrays();
+  if (fTrackProj) {
+    fTrackProj->Clear();
+    delete fTrackProj; fTrackProj = 0;
+  }
+}
+
+//_____________________________________________________________________________
+void THcHodoscope::DeleteArrays()
+{
+  // Delete member arrays. Used by destructor.
+
+  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 THcHodoscope::ClearEvent()
+{
+  // Reset per-event data.
+
+  const int lf = fNelem*sizeof(Double_t);
+  fLTNhit = 0;                            // Number of Left paddles TDC times
+  memset( fLT, 0, lf );                   // Left paddles TDCs
+  memset( fLT_c, 0, lf );                 // Left paddles corrected times
+  fRTNhit = 0;                            // Number of Right paddles TDC times
+  memset( fRT, 0, lf );                   // Right paddles TDCs
+  memset( fRT_c, 0, lf );                 // Right paddles corrected times
+  fLANhit = 0;                            // Number of Left paddles ADC amps
+  memset( fLA, 0, lf );                   // Left paddles ADCs
+  memset( fLA_p, 0, lf );                 // Left paddles ADC minus pedestal
+  memset( fLA_c, 0, lf );                 // Left paddles corrected ADCs
+  fRANhit = 0;                            // Number of Right paddles ADC smps
+  memset( fRA, 0, lf );                   // Right paddles ADCs
+  memset( fRA_p, 0, lf );                 // Right paddles ADC minus pedestal
+  memset( fRA_c, 0, lf );                 // Right paddles corrected ADCs
+  
+  fNhit = 0;
+  memset( fHitPad, 0, fNelem*sizeof(fHitPad[0]) );
+  memset( fTime, 0, lf );
+  memset( fdTime, 0, lf );
+  memset( fYt, 0, lf );
+  memset( fYa, 0, lf );
+  
+  fTrackProj->Clear();
+}
+
+//_____________________________________________________________________________
+Int_t THcHodoscope::Decode( const THaEvData& evdata )
+{
+  // Decode scintillator data, correct TDC times and ADC amplitudes, and copy
+  // the data to the local data members.
+  // This implementation makes the following assumptions about the detector map:
+  // - The first half of the map entries corresponds to ADCs, 
+  //   the second half, to TDCs.
+  // - The first fNelem detector channels correspond to the PMTs on the
+  //   right hand side, the next fNelem channels, to the left hand side.
+  //   (Thus channel numbering for each module must be consecutive.)
+
+  ClearEvent();
+
+  // Loop over all modules defined for Scintillator 1 detector
+
+  for( Int_t i = 0; i < fDetMap->GetSize(); i++ ) {
+    THaDetMap::Module* d = fDetMap->GetModule( i );
+    bool adc = ( d->model ? fDetMap->IsADC(d) : (i < fDetMap->GetSize()/2) );
+
+    // Loop over all channels that have a hit.
+    for( Int_t j = 0; j < evdata.GetNumChan( d->crate, d->slot ); j++) {
+
+      Int_t chan = evdata.GetNextChan( d->crate, d->slot, j );
+      if( chan < d->lo || chan > d->hi ) continue;     // Not one of my channels
+
+      // Get the data. Scintillators are assumed to have only single hit (hit=0)
+      Int_t data = evdata.GetData( d->crate, d->slot, chan, 0 );
+
+      // Get the detector channel number, starting at 0
+      Int_t k = d->first + chan - d->lo - 1;   
+
+#ifdef WITH_DEBUG      
+      if( k<0 || k>NDEST*fNelem ) {
+	// Indicates bad database
+	Warning( Here("Decode()"), "Illegal detector channel: %d", k );
+	continue;
+      }
+//        cout << "adc,j,k = " <<adc<<","<<j<< ","<<k<< endl;
+#endif
+      // Copy the data to the local variables.
+      DataDest* dest = fDataDest + k/fNelem;
+      k = k % fNelem;
+      if( adc ) {
+	dest->adc[k]   = static_cast<Double_t>( data );
+	dest->adc_p[k] = data - dest->ped[k];
+	dest->adc_c[k] = dest->adc_p[k] * dest->gain[k];
+	(*dest->nahit)++;
+      } else {
+	dest->tdc[k]   = static_cast<Double_t>( data );
+	dest->tdc_c[k] = (data - dest->offset[k])*fTdc2T;
+	(*dest->nthit)++;
+      }
+    }
+  }
+  if ( fDebug > 3 ) {
+    printf("\n\nEvent %d   Trigger %d Scintillator %s\n:",
+	   evdata.GetEvNum(), evdata.GetEvType(), GetPrefix() );
+    printf("   paddle  Left(TDC    ADC   ADC_p)   Right(TDC   ADC   ADC_p)\n");
+    for ( int i=0; i<fNelem; i++ ) {
+      printf("     %2d     %5.0f    %5.0f  %5.0f     %5.0f    %5.0f  %5.0f\n",
+	     i+1,fLT[i],fLA[i],fLA_p[i],fRT[i],fRA[i],fRA_p[i]);
+    }
+  }
+  
+  return fLTNhit+fRTNhit;
+}
+
+//_____________________________________________________________________________
+Int_t THcHodoscope::ApplyCorrections( void )
+{
+  // Apply the ADC/TDC corrections to get the 'REAL' relevant 
+  // TDC and ADC values. No tracking needs to have been done yet.
+  //
+  // Permits the dividing up of the decoding step (events could come from
+  // a different source) to the applying of corrections. For ease when
+  // trying to optimize calibrations
+  //
+  Int_t nlt=0, nrt=0, nla=0, nra=0;
+  for (Int_t i=0; i<fNelem; i++) {
+    if (fLA[i] != 0.) {
+      fLA_p[i] = fLA[i] - fLPed[i];
+      fLA_c[i] = fLA_p[i]*fLGain[i];
+      nla++;
+    }
+    if (fRA[i] != 0.) {
+      fRA_p[i] = fRA[i] - fRPed[i];
+      fRA_c[i] = fRA_p[i]*fRGain[i];
+      nra++;
+    }
+    if (fLT[i] != 0.) {
+      fLT_c[i] = (fLT[i] - fLOff[i])*fTdc2T - TimeWalkCorrection(i,kLeft);
+      nlt++;
+    }
+    if (fRT[i] != 0.) {
+      fRT_c[i] = (fRT[i] - fROff[i])*fTdc2T - TimeWalkCorrection(i,kRight);
+      nrt++;
+    }
+  }
+  // returns FALSE (0) if all matches up
+  return !(fLTNhit==nlt && fLANhit==nla && fRTNhit==nrt && fRANhit==nra );
+}
+
+//_____________________________________________________________________________
+Double_t THcHodoscope::TimeWalkCorrection(const Int_t& paddle,
+					     const ESide side)
+{
+  // Calculate the time-walk correction. The timewalk might be
+  // dependent upon the specific PMT, so information about exactly
+  // which PMT fired is required.
+  Double_t adc=0;
+  if (side == kLeft)
+    adc = fLA_p[paddle];
+  else
+    adc = fRA_p[paddle];
+
+  if (fNTWalkPar<=0 || !fTWalkPar) return 0.; // uninitialized return safe 0
+
+  // get the ADC value above the pedestal
+  if ( adc <=0. ) return 0.;
+  
+  // we have an arbitrary timing offset, and will declare here that
+  // for a MIP ( peak ~2000 ADC channels ) the timewalk correction is 0
+  
+  Double_t ref = fAdcMIP;
+  Double_t tw(0), tw_ref(0.);
+  int npar = fNTWalkPar/(2*fNelem);
+  
+  Double_t *par = &(fTWalkPar[npar*(side*fNelem+paddle)]);
+
+  tw = par[0]*pow(adc,-.5);
+  tw_ref = par[0]*pow(ref,-.5);
+
+  return tw-tw_ref;
+}
+
+//_____________________________________________________________________________
+Int_t THcHodoscope::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();
+
+  // count the number of paddles with complete TDC hits
+  // Fill in information available from timing
+  fNhit = 0;
+  for (int i=0; i<fNelem; i++) {
+    if (fLT[i]>0 && fRT[i]>0) {
+      fHitPad[fNhit++] = i;
+      fTime[i] = .5*(fLT_c[i]+fRT_c[i])-fSize[1]/fCn;
+      fdTime[i] = fResolution/sqrt2;
+      fYt[i] = .5*fCn*(fRT_c[i]-fLT_c[i]);
+    }
+
+    // rough calculation of position from ADC reading
+    if (fLA_c[i]>0&&fRA_c[i]>0) {
+      fYa[i] = TMath::Log(fLA_c[i]/fRA_c[i])/(2.*fAttenuation);
+      // rough dE/dX-like quantity, not correcting for track angle
+      fAmpl[i] = TMath::Sqrt(fLA_c[i]*fRA_c[i]*TMath::Exp(fAttenuation*2*fSize[1]))
+	/ fSize[2];
+    }
+  }
+  
+  return 0;
+}
+
+//_____________________________________________________________________________
+Int_t THcHodoscope::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.
+
+  int n_track = tracks.GetLast()+1;   // Number of reconstructed tracks
+  
+  Double_t dpadx = (2.*fSize[0])/(fNelem); // width of a paddle
+  // center of paddle '0'
+  Double_t padx0 = -dpadx*(fNelem-1)*.5;
+  
+  for ( int i=0; i<n_track; i++ ) {
+    THaTrack* theTrack = static_cast<THaTrack*>( tracks[i] );
+
+    Double_t pathl=kBig, xc=kBig, yc=kBig, dx=kBig;
+    Int_t pad=-1;
+    
+    if ( ! CalcTrackIntercept(theTrack, pathl, xc, yc) ) { // failed to hit
+      new ( (*fTrackProj)[i] )
+	THaTrackProj(xc,yc,pathl,dx,pad,this);
+      continue;
+    }
+    
+    // xc, yc are the positions of the track intercept
+    //  _RELATIVE TO THE DETECTOR PLANE's_ origin.
+    //
+    // look through set of complete hits for closest match
+    // loop through due to possible poor matches
+    dx = kBig;
+    for ( Int_t j=0; j<fNhit; j++ ) {
+      Double_t dx2 = ( padx0 + fHitPad[j]*dpadx) - xc;
+      if (TMath::Abs(dx2) < TMath::Abs(dx) ) {
+	pad = fHitPad[j];
+	dx = dx2;
+      }
+      else if (pad>=0) break; // stop after finding closest in X
+    }
+
+    // record information, found or not
+    new ( (*fTrackProj)[i] )
+      THaTrackProj(xc,yc,pathl,dx,pad,this);
+  }
+  
+  return 0;
+}
+
+ClassImp(THcHodoscope)
+////////////////////////////////////////////////////////////////////////////////
diff --git a/src/THcHodoscope.h b/src/THcHodoscope.h
new file mode 100644
index 0000000000000000000000000000000000000000..a093103c0e6841a456bf206333e50c6ea1343238
--- /dev/null
+++ b/src/THcHodoscope.h
@@ -0,0 +1,127 @@
+#ifndef ROOT_THaHodoscope
+#define ROOT_THaHodoscope
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// THaHodoscope                                                           //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+#include "TClonesArray.h"
+#include "THaNonTrackingDetector.h"
+
+class THaScCalib;
+
+class THaHodoscope : public THaNonTrackingDetector {
+
+public:
+  THaHodoscope( const char* name, const char* description = "",
+		   THaApparatus* a = NULL );
+  virtual ~THaHodoscope();
+
+  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; }
+  const Double_t* GetTimes() const { return fTime; }
+  const Double_t* GetTuncer() const { return fdTime; }
+  const Double_t* GetAmplitudes() const { return fAmpl; }
+  const Double_t* GetYtime() const { return fYt; }
+  const Double_t* GetYampl() const { return fYa; }
+  
+        Int_t GetNTracks() const { return fTrackProj->GetLast()+1; }
+  const TClonesArray* GetTrackHits() const { return fTrackProj; }
+  
+  friend class THaScCalib;
+
+  THaHodoscope();  // for ROOT I/O
+protected:
+
+  // Calibration
+  Double_t*   fLOff;       // [fNelem] TDC offsets for left paddles
+  Double_t*   fROff;       // [fNelem] TDC offsets for right paddles
+  Double_t*   fLPed;       // [fNelem] ADC pedestals for left paddles
+  Double_t*   fRPed;       // [fNelem] ADC pedestals for right paddles
+  Double_t*   fLGain;      // [fNelem] ADC gains for left paddles
+  Double_t*   fRGain;      // [fNelem] ADC gains for right paddles
+
+  Double_t    fTdc2T;      // linear conversion between TDC and time (s/ch)
+  Double_t    fCn;         // speed of light in material  (meters/second)
+
+  Int_t       fNTWalkPar;  // number of timewalk correction parameters
+  Double_t*   fTWalkPar;   // [fNTWalkPar] time walk correction parameters
+  Double_t    fAdcMIP;     // nominal ADC above pedestal for MIP
+
+  Double_t*   fTrigOff;     // [fNelem] Induced offset of trigger time from
+                            // diff between trigger and retiming.
+                            // Visible in coincidence data.
+
+  Double_t    fAttenuation; // in m^-1: attenuation length of material
+  Double_t    fResolution;  // average time resolution per PMT (s)
+
+  // Per-event data
+  Int_t       fLTNhit;     // Number of Left paddles TDC times
+  Double_t*   fLT;         // [fNelem] Array of Left paddles TDC times (channels)
+  Double_t*   fLT_c;       // [fNelem] Array of Left PMT corrected TDC times (s)
+  Int_t       fRTNhit;     // Number of Right paddles TDC times
+  Double_t*   fRT;         // [fNelem] Array of Right paddles TDC times (channels)
+  Double_t*   fRT_c;       // [fNelem] Array of Right PMT corrected TDC times (s)
+  Int_t       fLANhit;     // Number of Left paddles ADC amplitudes
+  Double_t*   fLA;         // [fNelem] Array of Left paddles ADC amplitudes
+  Double_t*   fLA_p;       // [fNelem] Array of Left paddles ADC minus ped values
+  Double_t*   fLA_c;       // [fNelem] Array of Left paddles corrected ADC ampl-s
+  Int_t       fRANhit;     // Number of Right paddles ADC amplitudes
+  Double_t*   fRA;         // [fNelem] Array of Right paddles ADC amplitudes
+  Double_t*   fRA_p;       // [fNelem] Array of Right paddles ADC minus ped values
+  Double_t*   fRA_c;       // [fNelem] Array of Right paddles corrected ADC ampl-s
+
+  
+  Int_t      fNhit;       // Number of paddles with complete TDC hits (l&r)
+  Int_t*     fHitPad;     // [fNhit] list of paddles with complete TDC hits
+
+  // could be done on a per-hit basis instead
+  Double_t*   fTime;       // [fNelem] corrected time for the paddle (s)
+  Double_t*   fdTime;      // [fNelem] uncertainty in time (s)
+  Double_t*   fAmpl;       // [fNelem] overall amplitude for the paddle
+  Double_t*   fYt;         // [fNelem] y-position of hit in paddle from TDC (m)
+  Double_t*   fYa;         // [fNelem] y-position of hit in paddle from ADC (m)
+  
+  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 );
+
+  enum ESide { kLeft = 0, kRight = 1 };
+  
+  virtual  Double_t TimeWalkCorrection(const Int_t& paddle,
+					   const ESide side);
+
+  ClassDef(THaHodoscope,0)   // Generic scintillator class
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/src/THcNonTrackingDetector.cxx b/src/THcNonTrackingDetector.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..2f76e1f3873bd73587e05dca8b01d201c481978b
--- /dev/null
+++ b/src/THcNonTrackingDetector.cxx
@@ -0,0 +1,37 @@
+//*-- Author :    Ole Hansen   7-Sep-00
+
+//////////////////////////////////////////////////////////////////////////
+//
+// THaNonTrackingDetector
+//
+//////////////////////////////////////////////////////////////////////////
+
+#include "THaNonTrackingDetector.h"
+
+ClassImp(THaNonTrackingDetector)
+
+//______________________________________________________________________________
+THaNonTrackingDetector::THaNonTrackingDetector( const char* name, 
+						const char* description,
+						THaApparatus* apparatus )
+  : THaSpectrometerDetector(name,description,apparatus)
+{
+  // Normal constructor with name and description
+
+}
+
+//______________________________________________________________________________
+THaNonTrackingDetector::THaNonTrackingDetector( )
+  : THaSpectrometerDetector( )
+{
+  // for ROOT I/O only
+
+}
+
+//______________________________________________________________________________
+THaNonTrackingDetector::~THaNonTrackingDetector()
+{
+  // Destructor
+
+}
+
diff --git a/src/THcNonTrackingDetector.h b/src/THcNonTrackingDetector.h
new file mode 100644
index 0000000000000000000000000000000000000000..a0ff050e79f43a85d089f37b69c85062af74a827
--- /dev/null
+++ b/src/THcNonTrackingDetector.h
@@ -0,0 +1,41 @@
+#ifndef ROOT_THaNonTrackingDetector
+#define ROOT_THaNonTrackingDetector
+
+//////////////////////////////////////////////////////////////////////////
+//
+// THaNonTrackingDetector.h
+//
+// Abstract base class for a generic non-tracking spectrometer detector. 
+//
+// This is a special THaSpectrometerDetector -- any detector that
+// is not a tracking detector.  This includes PID detectors.
+//
+//////////////////////////////////////////////////////////////////////////
+
+#include "THaSpectrometerDetector.h"
+
+class TClonesArray;
+
+class THaNonTrackingDetector : public THaSpectrometerDetector {
+  
+public:
+  THaNonTrackingDetector(); // only for ROOT I/O
+
+  virtual ~THaNonTrackingDetector();
+  
+  virtual Int_t    CoarseProcess( TClonesArray& tracks ) = 0;
+  virtual Int_t    FineProcess( TClonesArray& tracks )  = 0;
+          Bool_t   IsTracking() { return kFALSE; }
+  virtual Bool_t   IsPid()      { return kFALSE; }
+
+protected:
+
+  //Only derived classes may construct me for real
+
+  THaNonTrackingDetector( const char* name, const char* description,
+			  THaApparatus* a = NULL);
+
+  ClassDef(THaNonTrackingDetector,1)  //ABC for a non-tracking spectrometer detector
+};
+
+#endif
diff --git a/src/THcSpectrometerDetector.cxx b/src/THcSpectrometerDetector.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..9b33f48effb0415e2bb67a2d70479f35a432652c
--- /dev/null
+++ b/src/THcSpectrometerDetector.cxx
@@ -0,0 +1,96 @@
+//*-- Author :    Ole Hansen   7-Sep-00
+
+//////////////////////////////////////////////////////////////////////////
+//
+// THaSpectrometerDetector
+//
+//////////////////////////////////////////////////////////////////////////
+
+#include "THaSpectrometerDetector.h"
+#include "THaTrack.h"
+#include "TMath.h"
+
+ClassImp(THaSpectrometerDetector)
+
+//______________________________________________________________________________
+THaSpectrometerDetector::THaSpectrometerDetector( const char* name, 
+						  const char* description,
+						  THaApparatus* apparatus )
+  : THaDetector(name,description,apparatus)
+{
+  // Constructor
+
+}
+
+//______________________________________________________________________________
+THaSpectrometerDetector::THaSpectrometerDetector( )
+{
+  // Constructor for ROOT I/O only
+}
+
+//______________________________________________________________________________
+THaSpectrometerDetector::~THaSpectrometerDetector()
+{
+  // Destructor
+
+}
+
+//_____________________________________________________________________________
+void THaSpectrometerDetector::DefineAxes(Double_t rotation_angle)
+{
+  // define variables used for calculating intercepts of tracks
+  // with the detector
+  // right now, we assume that all detectors except VDCs are 
+  // perpendicular to the Transport frame
+
+  fXax.SetXYZ( TMath::Cos(rotation_angle), 0.0, TMath::Sin(rotation_angle) );
+  fYax.SetXYZ( 0.0, 1.0, 0.0 );
+  fZax = fXax.Cross(fYax);
+
+}
+
+//_____________________________________________________________________________
+bool THaSpectrometerDetector::CalcTrackIntercept(THaTrack* theTrack, 
+					 Double_t& t, Double_t& xcross, 
+					 Double_t& ycross)
+{
+  // projects a given track on to the plane of the detector
+  // xcross and ycross are the x and y coords of this intersection
+  // t is the distance from the origin of the track to the given plane.
+  // 
+  // If a hit is NOT found, then t, xcross, and ycross are unchanged.
+  TVector3 t0( theTrack->GetX(), theTrack->GetY(), 0.0 );
+  Double_t norm = TMath::Sqrt(1.0 + theTrack->GetTheta()*theTrack->GetTheta() +
+			      theTrack->GetPhi()*theTrack->GetPhi());
+  TVector3 t_hat( theTrack->GetTheta()/norm, theTrack->GetPhi()/norm, 1.0/norm );
+
+  TVector3 v;
+  if( !IntersectPlaneWithRay( fXax, fYax, fOrigin, t0, t_hat, t, v ))
+    return false;
+  v -= fOrigin;
+  xcross = v.Dot(fXax);
+  ycross = v.Dot(fYax);
+
+  return true;
+}
+
+//_____________________________________________________________________________
+bool THaSpectrometerDetector::CheckIntercept(THaTrack *track)
+{
+  Double_t x, y, t;
+  return CalcTrackIntercept(track, t, x, y);
+}
+
+//_____________________________________________________________________________
+bool THaSpectrometerDetector::CalcInterceptCoords(THaTrack* track, Double_t& x, Double_t& y)
+{
+  Double_t t;
+  return CalcTrackIntercept(track, t, x, y);
+}
+
+//_____________________________________________________________________________
+bool THaSpectrometerDetector::CalcPathLen(THaTrack* track, Double_t& t)
+{
+  Double_t x, y;
+  return CalcTrackIntercept(track, t, x, y);
+}
diff --git a/src/THcSpectrometerDetector.h b/src/THcSpectrometerDetector.h
new file mode 100644
index 0000000000000000000000000000000000000000..e9f1faedbdc635e73c6d9e6678f0fb7d16183a1c
--- /dev/null
+++ b/src/THcSpectrometerDetector.h
@@ -0,0 +1,53 @@
+#ifndef ROOT_THaSpectrometerDetector
+#define ROOT_THaSpectrometerDetector
+
+//////////////////////////////////////////////////////////////////////////
+//
+// THaSpectrometerDetector
+//
+// Abstract base class for a generic spectrometer detector. 
+//
+// This is a specialized detector class that supports the concept of
+// "tracking" and "PID" detectors.
+//
+//////////////////////////////////////////////////////////////////////////
+
+#include "THaDetector.h"
+
+class THaTrack;
+
+class THaSpectrometerDetector : public THaDetector {
+  
+public:
+  virtual ~THaSpectrometerDetector();
+  
+  virtual Bool_t   IsTracking() = 0;
+  virtual Bool_t   IsPid()      = 0;
+
+          bool     CheckIntercept( THaTrack* track );
+          bool     CalcInterceptCoords( THaTrack* track, 
+					Double_t& x, Double_t& y );
+          bool     CalcPathLen( THaTrack* track, Double_t& t );
+
+  THaSpectrometerDetector();       // for ROOT I/O only
+
+protected:
+
+  // Geometry data
+  TVector3  fXax;                  // X axis of the detector plane
+  TVector3  fYax;                  // Y axis of the detector plane
+  TVector3  fZax;                  // Normal to the detector plane
+
+  virtual void  DefineAxes( Double_t rotation_angle );
+
+          bool  CalcTrackIntercept( THaTrack* track, Double_t& t, 
+				    Double_t& ycross, Double_t& xcross);
+
+  //Only derived classes may construct me
+  THaSpectrometerDetector( const char* name, const char* description,
+			   THaApparatus* a = NULL );
+
+  ClassDef(THaSpectrometerDetector,1)   //ABC for a spectrometer detector
+};
+
+#endif