diff --git a/Makefile b/Makefile
index fadfb2944800f96524642667e412b4977efa1e24..422e44b8456bc4d1847309026d5fb6da4dcf2d4b 100644
--- a/Makefile
+++ b/Makefile
@@ -15,7 +15,8 @@ SRC  =  src/THcInterface.cxx src/THcParmList.cxx src/THcAnalyzer.cxx \
 	src/THcSignalHit.cxx \
 	src/THcHodoscope.cxx src/THcScintillatorPlane.cxx \
 	src/THcHodoscopeHit.cxx \
-	src/THcDriftChamber.cxx src/THcDriftChamberPlane.cxx \
+	src/THcDC.cxx src/THcDriftChamberPlane.cxx \
+	src/THcDriftChamber.cxx \
 	src/THcRawDCHit.cxx src/THcDCHit.cxx \
 	src/THcDCWire.cxx \
 	src/THcDCLookupTTDConv.cxx src/THcDCTimeToDistConv.cxx \
diff --git a/examples/hodtest.C b/examples/hodtest.C
index b92846d97e26933fda03fd850882f1a6bf5c9d6c..982e284adffdc261d98dec97cbf39ec5f105b017 100644
--- a/examples/hodtest.C
+++ b/examples/hodtest.C
@@ -38,7 +38,7 @@
   // Add hodoscope
   HMS->AddDetector( new THcHodoscope("hod", "Hodoscope" ));
   HMS->AddDetector( new THcShower("cal", "Shower" ));
-  HMS->AddDetector( new THcDriftChamber("dc", "Drift Chambers" ));
+  HMS->AddDetector( new THcDC("dc", "Drift Chambers" ));
   THcAerogel* aerogel = new THcAerogel("aero", "Aerogel Cerenkov" );
   HMS->AddDetector( aerogel );
 
diff --git a/examples/hodtest_cuts.def b/examples/hodtest_cuts.def
index 6ccbe52ceb55b33618ab5f59c576546ffe17aa64..f6003c2200a18b2f4d7156e51c0250c8b5ce2b06 100644
--- a/examples/hodtest_cuts.def
+++ b/examples/hodtest_cuts.def
@@ -9,6 +9,9 @@ RawDecode_master  1
 Block: Decode
 Decode_master     !Pedestal_event
 
+Block: CoarseTracking
+CoarseTracking_master !Pedestal_event
+
 Block: CoarseReconstruct
 RawCoarseReconstruct !Pedestal_event
 
diff --git a/src/HallC_LinkDef.h b/src/HallC_LinkDef.h
index 608c0041beef3679cbdce6befbbf801ca61abd6d..ce520fa067dda33b10aebdad9bebadeb2336f719 100644
--- a/src/HallC_LinkDef.h
+++ b/src/HallC_LinkDef.h
@@ -18,6 +18,7 @@
 #pragma link C++ class THcHodoscope+;
 #pragma link C++ class THcScintillatorPlane+;
 #pragma link C++ class THcHodoscopeHit+;
+#pragma link C++ class THcDC+;
 #pragma link C++ class THcDriftChamber+;
 #pragma link C++ class THcDriftChamberPlane+;
 #pragma link C++ class THcRawDCHit+;
diff --git a/src/THcDC.cxx b/src/THcDC.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..07eb1c6c3534741db4816b3df667b231e25018f9
--- /dev/null
+++ b/src/THcDC.cxx
@@ -0,0 +1,430 @@
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// THcDC                                                              //
+//                                                                           //
+// 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 "THcDC.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;
+
+//_____________________________________________________________________________
+THcDC::THcDC(
+ const char* name, const char* description,
+				  THaApparatus* apparatus ) :
+  THaTrackingDetector(name,description,apparatus)
+{
+  // Constructor
+
+  //  fTrackProj = new TClonesArray( "THaTrackProj", 5 );
+  fNPlanes = 0;			// No planes until we make them
+
+}
+
+//_____________________________________________________________________________
+void THcDC::Setup(const char* name, const char* description)
+{
+
+  char prefix[2];
+  char parname[100];
+
+  THaApparatus *app = GetApparatus();
+  if(app) {
+    cout << app->GetName() << endl;
+  } else {
+    cout << "No apparatus found" << endl;
+  }
+
+  prefix[0]=tolower(app->GetName()[0]);
+  prefix[1]='\0';
+
+  string planenamelist;
+  DBRequest list[]={
+    {"dc_num_planes",&fNPlanes, kInt},
+    {"dc_num_chambers",&fNChambers, kInt},
+    {"dc_tdc_time_per_channel",&fNSperChan, kDouble},
+    {"dc_wire_velocity",&fWireVelocity,kDouble},
+    {"dc_plane_names",&planenamelist, kString},
+    {0}
+  };
+
+  gHcParms->LoadParmValues((DBRequest*)&list,prefix);
+  cout << planenamelist << endl;
+  cout << "Drift Chambers: " <<  fNPlanes << " planes in " << fNChambers << " chambers" << endl;
+
+  vector<string> plane_names = vsplit(planenamelist);
+
+  if(plane_names.size() != (UInt_t) fNPlanes) {
+    cout << "ERROR: Number of planes " << fNPlanes << " doesn't agree with number of plane names " << plane_names.size() << endl;
+    // Should quit.  Is there an official way to quit?
+  }
+  fPlaneNames = new char* [fNPlanes];
+  for(Int_t i=0;i<fNPlanes;i++) {
+    fPlaneNames[i] = new char[plane_names[i].length()];
+    strcpy(fPlaneNames[i], plane_names[i].c_str());
+  }
+
+  char *desc = new char[strlen(description)+100];
+  fPlanes = new THcDriftChamberPlane* [fNPlanes];
+
+  for(Int_t i=0;i<fNPlanes;i++) {
+    strcpy(desc, description);
+    strcat(desc, " Plane ");
+    strcat(desc, fPlaneNames[i]);
+
+    fPlanes[i] = new THcDriftChamberPlane(fPlaneNames[i], desc, i+1, this);
+    cout << "Created Drift Chamber Plane " << fPlaneNames[i] << ", " << desc << endl;
+
+  }
+  fChambers = new THcDriftChamber* [fNChambers];
+  for(Int_t i=0;i<fNChambers;i++) {
+    sprintf(desc,"%s Chamber %d",description, i+1);
+
+    // Should construct a better chamber name
+    fChambers[i] = new THcDriftChamber(desc, desc, i+1, this);
+    cout << "Created Drift Chamber " << i+1 << ", " << desc << endl;
+    
+    
+  }
+}
+
+//_____________________________________________________________________________
+THcDC::THcDC( ) :
+  THaTrackingDetector()
+{
+  // Constructor
+}
+
+//_____________________________________________________________________________
+THaAnalysisObject::EStatus THcDC::Init( const TDatime& date )
+{
+  static const char* const here = "Init()";
+
+  Setup(GetName(), GetTitle());	// Create the subdetectors here
+  
+  // Should probably put this in ReadDatabase as we will know the
+  // maximum number of hits after setting up the detector map
+  THcHitList::InitHitList(fDetMap, "THcRawDCHit", 1000);
+
+  EStatus status;
+  // This triggers call of ReadDatabase and DefineVariables
+  if( (status = THaTrackingDetector::Init( date )) )
+    return fStatus=status;
+
+  // Initialize planes and add them to chambers
+  for(Int_t ip=0;ip<fNPlanes;ip++) {
+    if((status = fPlanes[ip]->Init( date ))) {
+      return fStatus=status;
+    } else {
+      Int_t chamber=fNChamber[ip];
+      fChambers[chamber-1]->AddPlane(fPlanes[ip]);
+    }
+  }
+  // Initialize chambers
+  for(Int_t ic=0;ic<fNChambers;ic++) {
+    if((status = fChambers[ic]->Init ( date ))) {
+      return fStatus=status;
+    }
+  }
+
+  // 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) );
+
+  // Will need to determine which apparatus it belongs to and use the
+  // appropriate detector ID in the FillMap call
+  char EngineDID[4];
+
+  EngineDID[0] = toupper(GetApparatus()->GetName()[0]);
+  EngineDID[1] = 'D';
+  EngineDID[2] = 'C';
+  EngineDID[3] = '\0';
+  
+  if( gHcDetectorMap->FillMap(fDetMap, EngineDID) < 0 ) {
+    Error( Here(here), "Error filling detectormap for %s.", 
+	     EngineDID);
+      return kInitError;
+  }
+
+  return fStatus = kOK;
+}
+
+//_____________________________________________________________________________
+Int_t THcDC::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()";
+  char prefix[2];
+  char parname[100];
+
+  // Read data from database 
+  // Pull values from the THcParmList instead of reading a database
+  // file like Hall A does.
+
+  // 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)
+
+  prefix[0]=tolower(GetApparatus()->GetName()[0]);
+
+  prefix[1]='\0';
+
+  fXCenter = new Double_t [fNChambers];
+  fYCenter = new Double_t [fNChambers];
+  fMinHits = new Int_t [fNChambers];
+  fMaxHits = new Int_t [fNChambers];
+  fMinCombos = new Int_t [fNChambers];
+  fSpace_Point_Criterion2 = new Double_t [fNChambers];
+
+  fTdcWinMin = new Int_t [fNPlanes];
+  fTdcWinMax = new Int_t [fNPlanes];
+  fCentralTime = new Int_t [fNPlanes];
+  fNWires = new Int_t [fNPlanes];
+  fNChamber = new Int_t [fNPlanes]; // Which chamber is this plane
+  fWireOrder = new Int_t [fNPlanes]; // Wire readout order
+  fDriftTimeSign = new Int_t [fNPlanes];
+
+  fZPos = new Double_t [fNPlanes];
+  fAlphaAngle = new Double_t [fNPlanes];
+  fBetaAngle = new Double_t [fNPlanes];
+  fGammaAngle = new Double_t [fNPlanes];
+  fPitch = new Double_t [fNPlanes];
+  fCentralWire = new Double_t [fNPlanes];
+  fPlaneTimeZero = new Double_t [fNPlanes];
+
+
+  DBRequest list[]={
+    {"dc_tdc_time_per_channel",&fNSperChan, kDouble},
+    {"dc_wire_velocity",&fWireVelocity,kDouble},
+
+    {"dc_xcenter", fXCenter, kDouble, fNChambers},
+    {"dc_ycenter", fYCenter, kDouble, fNChambers},
+    {"min_hit", fMinHits, kInt, fNChambers},
+    {"max_pr_hits", fMaxHits, kInt, fNChambers},
+    {"min_combos", fMinCombos, kInt, fNChambers},
+    {"space_point_criterion", fSpace_Point_Criterion2, kDouble, fNChambers},
+
+    {"dc_tdc_min_win", fTdcWinMin, kInt, fNPlanes},
+    {"dc_tdc_max_win", fTdcWinMax, kInt, fNPlanes},
+    {"dc_central_time", fCentralTime, kInt, fNPlanes},
+    {"dc_nrwire", fNWires, kInt, fNPlanes},
+    {"dc_chamber_planes", fNChamber, kInt, fNPlanes},
+    {"dc_wire_counting", fWireOrder, kInt, fNPlanes},
+    {"dc_drifttime_sign", fDriftTimeSign, kInt, fNPlanes},
+
+    {"dc_zpos", fZPos, kDouble, fNPlanes},
+    {"dc_alpha_angle", fAlphaAngle, kDouble, fNPlanes},
+    {"dc_beta_angle", fBetaAngle, kDouble, fNPlanes},
+    {"dc_gamma_angle", fGammaAngle, kDouble, fNPlanes},
+    {"dc_pitch", fPitch, kDouble, fNPlanes},
+    {"dc_central_wire", fCentralWire, kDouble, fNPlanes},
+    {"dc_plane_time_zero", fPlaneTimeZero, kDouble, fNPlanes},
+    {0}
+  };
+  gHcParms->LoadParmValues((DBRequest*)&list,prefix);
+
+  cout << "Plane counts:";
+  for(Int_t i=0;i<fNPlanes;i++) {
+    cout << " " << fNWires[i];
+  }
+  cout << endl;
+
+  fIsInit = true;
+
+  return kOK;
+}
+
+//_____________________________________________________________________________
+Int_t THcDC::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[] = {
+    { "nhit", "Number of DC hits",  "fNhits" },
+    { 0 }
+  };
+  return DefineVarsFromList( vars, mode );
+
+}
+
+//_____________________________________________________________________________
+THcDC::~THcDC()
+{
+  // Destructor. Remove variables from global list.
+
+  if( fIsSetup )
+    RemoveVariables();
+  if( fIsInit )
+    DeleteArrays();
+  if (fTrackProj) {
+    fTrackProj->Clear();
+    delete fTrackProj; fTrackProj = 0;
+  }
+}
+
+//_____________________________________________________________________________
+void THcDC::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 THcDC::ClearEvent()
+{
+  // Reset per-event data.
+  fNhits = 0;
+
+  for(Int_t i=0;i<fNChambers;i++) {
+    fChambers[i]->Clear();
+  }
+
+  
+  //  fTrackProj->Clear();
+}
+
+//_____________________________________________________________________________
+Int_t THcDC::Decode( const THaEvData& evdata )
+{
+
+  ClearEvent();
+
+  // Get the Hall C style hitlist (fRawHitList) for this event
+  fNhits = THcHitList::DecodeToHitList(evdata);
+
+  // Let each plane get its hits
+  Int_t nexthit = 0;
+  for(Int_t ip=0;ip<fNPlanes;ip++) {
+    nexthit = fPlanes[ip]->ProcessHits(fRawHitList, nexthit);
+  }
+
+  // Let each chamber get its hits
+  for(Int_t ic=0;ic<fNChambers;ic++) {
+    fChambers[ic]->ProcessHits();
+  }
+#if 0
+  // fRawHitList is TClones array of THcRawDCHit objects
+  for(Int_t ihit = 0; ihit < fNRawHits ; ihit++) {
+    THcRawDCHit* hit = (THcRawDCHit *) 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;
+#endif
+
+  return fNhits;
+}
+
+//_____________________________________________________________________________
+Int_t THcDC::ApplyCorrections( void )
+{
+  return(0);
+}
+
+//_____________________________________________________________________________
+Int_t THcDC::CoarseTrack( 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.);
+  for(Int_t i=0;i<fNChambers;i++) {
+
+    fChambers[i]->FindSpacePoints();
+  }
+
+  ApplyCorrections();
+
+  return 0;
+}
+
+//_____________________________________________________________________________
+Int_t THcDC::FineTrack( 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(THcDC)
+////////////////////////////////////////////////////////////////////////////////
diff --git a/src/THcDC.h b/src/THcDC.h
new file mode 100644
index 0000000000000000000000000000000000000000..d73491b49572d829720744d6f038eda2db06e7f0
--- /dev/null
+++ b/src/THcDC.h
@@ -0,0 +1,145 @@
+#ifndef ROOT_THcDC
+#define ROOT_THcDC
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// THcDC                                                           //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+#include "THaTrackingDetector.h"
+#include "THcHitList.h"
+#include "THcRawDCHit.h"
+#include "THcDriftChamberPlane.h"
+#include "THcDriftChamber.h"
+#include "TMath.h"
+
+//class THaScCalib;
+class TClonesArray;
+
+class THcDC : public THaTrackingDetector, public THcHitList {
+
+public:
+  THcDC( const char* name, const char* description = "",
+		   THaApparatus* a = NULL );
+  virtual ~THcDC();
+
+  virtual Int_t      Decode( const THaEvData& );
+  virtual EStatus    Init( const TDatime& run_time );
+  virtual Int_t      CoarseTrack( TClonesArray& tracks );
+  virtual Int_t      FineTrack( 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; }
+
+  Int_t GetNWires(Int_t plane) const { return fNWires[plane-1];}
+  Int_t GetNChamber(Int_t plane) const { return fNChamber[plane-1];}
+  Int_t GetWireOrder(Int_t plane) const { return fWireOrder[plane-1];}
+  Int_t GetPitch(Int_t plane) const { return fPitch[plane-1];}
+  Int_t GetCentralWire(Int_t plane) const { return fCentralWire[plane-1];}
+  Int_t GetTdcWinMin(Int_t plane) const { return fTdcWinMin[plane-1];}
+  Int_t GetTdcWinMax(Int_t plane) const { return fTdcWinMax[plane-1];}
+
+  Double_t GetAlphaAngle(Int_t plane) const { return fAlphaAngle[plane-1];}
+  Double_t GetBetaAngle(Int_t plane) const { return fBetaAngle[plane-1];}
+  Double_t GetGammaAngle(Int_t plane) const { return fGammaAngle[plane-1];}
+
+  Int_t GetMinHits(Int_t chamber) const { return fMinHits[chamber-1];}
+  Int_t GetMaxHits(Int_t chamber) const { return fMaxHits[chamber-1];}
+  Int_t GetMinCombos(Int_t chamber) const { return fMinCombos[chamber-1];}
+  Double_t GetSpacePointCriterion(Int_t chamber) const { return TMath::Sqrt(fSpace_Point_Criterion2[chamber-1]);}
+
+  Double_t GetPlaneTimeZero(Int_t plane) const { return fPlaneTimeZero[plane-1];}
+
+  Double_t GetNSperChan() const { return fNSperChan;}
+
+  Double_t GetCenter(Int_t plane) const {
+    Int_t chamber = GetNChamber(plane)-1;
+    return
+      fXCenter[chamber]*sin(fAlphaAngle[plane-1]) +
+      fYCenter[chamber]*cos(fAlphaAngle[plane-1]);
+  }
+  //  friend class THaScCalib;
+
+  THcDC();  // for ROOT I/O
+protected:
+
+  // Calibration
+
+  // Per-event data
+  Int_t fNhits;
+
+  // Potential Hall C parameters.  Mostly here for demonstration
+  Int_t fNPlanes;
+  char** fPlaneNames;
+  Int_t fNChambers;
+
+  Double_t fNSperChan;		/* TDC bin size */
+  Double_t fWireVelocity;
+
+  // Each of these will be dimensioned with the number of chambers
+  Double_t* fXCenter;
+  Double_t* fYCenter;
+  Int_t* fMinHits;
+  Int_t* fMaxHits;
+  Int_t* fMinCombos;
+  Double_t* fSpace_Point_Criterion2;
+
+  // Each of these will be dimensioned with the number of planes
+  // A THcDCPlane class object will need to access the value for
+  // its plane number.  Should we have a Get method for each or 
+  Int_t* fTdcWinMin;
+  Int_t* fTdcWinMax;
+  Int_t* fCentralTime;
+  Int_t* fNWires;		// Number of wires per plane
+  Int_t* fNChamber;
+  Int_t* fWireOrder;
+  Int_t* fDriftTimeSign;
+
+  Double_t* fZPos;
+  Double_t* fAlphaAngle;
+  Double_t* fBetaAngle;
+  Double_t* fGammaAngle;
+  Double_t* fPitch;
+  Double_t* fCentralWire;
+  Double_t* fPlaneTimeZero;
+
+  THcDriftChamberPlane** fPlanes; // List of plane objects
+  THcDriftChamber** fChambers; // List of chamber objects
+
+  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 );
+
+  void Setup(const char* name, const char* description);
+
+  ClassDef(THcDC,0)   // Drift Chamber class
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/src/THcDCHit.cxx b/src/THcDCHit.cxx
index 0484b1ad39d1f2d1ee0171dfe0d2f5194f6a0ce0..3b1523c444ce0d4088ab5b422359d7e3d1cfd9ac 100644
--- a/src/THcDCHit.cxx
+++ b/src/THcDCHit.cxx
@@ -9,10 +9,31 @@
 #include "THcDCHit.h"
 #include "THcDCTimeToDistConv.h"
 
+#include <iostream>
+
+using std::cout;
+using std::endl;
+
 ClassImp(THcDCHit)
 
 const Double_t THcDCHit::kBig = 1.e38; // Arbitrary large value
 
+//_____________________________________________________________________________
+void THcDCHit::Print( Option_t* opt ) const
+{
+  // Print hit info
+
+  cout << "Hit: wire=" << GetWireNum()
+       << "/" << (fWirePlane ? fWirePlane->GetName() : "??")
+       << " wpos="     << GetPos()
+       << " time="     << GetTime()
+       << " drift="    << GetDist();
+  //       << " res="      << GetResolution()
+    //       << " z="        << GetZ()
+  if( *opt != 'C' )
+    cout << endl;
+}
+
 //_____________________________________________________________________________
 Double_t THcDCHit::ConvertTimeToDist()
 {
@@ -51,15 +72,17 @@ Int_t THcDCHit::Compare( const TObject* obj ) const
  
   Int_t myWireNum = fWire->GetNum();
   Int_t hitWireNum = hit->GetWire()->GetNum();
-  // Compare wire numbers
+  Int_t myPlaneNum = GetPlaneNum();
+  Int_t hitPlaneNum = hit->GetPlaneNum();
+  if (myPlaneNum < hitPlaneNum) return -1;
+  if (myPlaneNum > hitPlaneNum) return 1;
+  // If planes are the same, compare wire numbers
   if (myWireNum < hitWireNum) return -1;
   if (myWireNum > hitWireNum) return  1;
-  if (myWireNum == hitWireNum) {
-    // If wire numbers are the same, compare times
-    Double_t hitTime = hit->GetTime();
-    if (fTime < hitTime) return -1;
-    if (fTime > hitTime) return  1;
-  }
+  // If wire numbers are the same, compare times
+  Double_t hitTime = hit->GetTime();
+  if (fTime < hitTime) return -1;
+  if (fTime > hitTime) return  1;
   return 0;
 }
 
diff --git a/src/THcDCHit.h b/src/THcDCHit.h
index 79f88e7123f7a8d39d805719e7ce2b74ec831316..fb886f6b1138ecea0d8ef53b757a4a15786c7d21 100644
--- a/src/THcDCHit.h
+++ b/src/THcDCHit.h
@@ -9,13 +9,17 @@
 
 #include "TObject.h"
 #include "THcDCWire.h"
+#include "THcDriftChamberPlane.h"
+#include "THcDriftChamber.h"
 #include <cstdio>
 
 class THcDCHit : public TObject {
 
 public:
-  THcDCHit( THcDCWire* wire=NULL, Int_t rawtime=0, Double_t time=0.0 ) : 
-    fWire(wire), fRawTime(rawtime), fTime(time), fDist(0.0), ftrDist(kBig) {
+ THcDCHit( THcDCWire* wire=NULL, Int_t rawtime=0, Double_t time=0.0,
+	   THcDriftChamberPlane* wp=0) : 
+  fWire(wire), fRawTime(rawtime), fTime(time), fWirePlane(wp),
+    fDist(0.0), ftrDist(kBig) {
       ConvertTimeToDist();
     }
   virtual ~THcDCHit() {}
@@ -23,6 +27,7 @@ public:
   virtual Double_t ConvertTimeToDist();
   Int_t  Compare ( const TObject* obj ) const;
   Bool_t IsSortable () const { return kTRUE; }
+  virtual void Print( Option_t* opt="" ) const;
   
   // Get and Set Functions
   THcDCWire* GetWire() const { return fWire; }
@@ -33,22 +38,32 @@ public:
   Double_t GetPos()     const { return fWire->GetPos(); } //Position of hit wire
   Double_t GetdDist()   const { return fdDist; }
 
+  THcDriftChamberPlane* GetWirePlane() const { return fWirePlane; }
+  
+
   void     SetWire(THcDCWire * wire) { fWire = wire; }
   void     SetRawTime(Int_t time)     { fRawTime = time; }
   void     SetTime(Double_t time)     { fTime = time; }
   void     SetDist(Double_t dist)     { fDist = dist; }
   void     SetdDist(Double_t ddist)   { fdDist = ddist; }
   void     SetFitDist(Double_t dist)  { ftrDist = dist; }
+  Int_t    GetPlaneNum() const { return fWirePlane->GetPlaneNum(); }
+  Int_t    GetPlaneIndex() const { return fWirePlane->GetPlaneIndex(); }
+  Int_t    GetChamberNum() const { return fWirePlane->GetChamberNum(); }
   
 protected:
   static const Double_t kBig;  //!
   
-  THcDCWire* fWire;     // Wire on which the hit occurred
+  THcDCWire*  fWire;     // Wire on which the hit occurred
   Int_t       fRawTime;  // TDC value (channels)
   Double_t    fTime;     // Time corrected for time offset of wire (s)
+  THcDriftChamberPlane* fWirePlane; //! Pointer to parent wire plane
   Double_t    fDist;     // (Perpendicular) Drift Distance
   Double_t    fdDist;    // uncertainty in fDist (for chi2 calc)
   Double_t    ftrDist;   // (Perpendicular) distance from the track
+
+  THcDriftChamber* fChamber; //! Pointer to parent wire plane
+
   
  private:
   THcDCHit( const THcDCHit& );
diff --git a/src/THcDriftChamber.cxx b/src/THcDriftChamber.cxx
index 1d53b20c58f52e7465596ea9240a58bd1755eb6b..1a77d4d7f230f59aaed0cc5349e44412130cb4dc 100644
--- a/src/THcDriftChamber.cxx
+++ b/src/THcDriftChamber.cxx
@@ -1,18 +1,17 @@
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
-// THcDriftChamber                                                              //
+// 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.                                      //
+// Subdetector class to hold a bunch of planes constituting a chamber        //
+// This class will be created by the THcDC class which will also create      //
+// the plane objects.                                                        //
+// The THcDC class will then pass this class a list of the planes.           //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
 #include "THcDriftChamber.h"
-#include "THaEvData.h"
-#include "THaDetMap.h"
-#include "THcDetectorMap.h"
+#include "THcDC.h"
+#include "THcDCHit.h"
 #include "THcGlobals.h"
 #include "THcParmList.h"
 #include "VarDef.h"
@@ -33,14 +32,16 @@ using namespace std;
 //_____________________________________________________________________________
 THcDriftChamber::THcDriftChamber(
  const char* name, const char* description,
-				  THaApparatus* apparatus ) :
-  THaTrackingDetector(name,description,apparatus)
+ const Int_t chambernum, THaDetectorBase* parent ) :
+  THaSubDetector(name,description,parent)
 {
   // Constructor
 
   //  fTrackProj = new TClonesArray( "THaTrackProj", 5 );
   fNPlanes = 0;			// No planes until we make them
 
+  fChamberNum = chambernum;
+
 }
 
 //_____________________________________________________________________________
@@ -48,7 +49,6 @@ void THcDriftChamber::Setup(const char* name, const char* description)
 {
 
   char prefix[2];
-  char parname[100];
 
   THaApparatus *app = GetApparatus();
   if(app) {
@@ -60,181 +60,92 @@ void THcDriftChamber::Setup(const char* name, const char* description)
   prefix[0]=tolower(app->GetName()[0]);
   prefix[1]='\0';
 
-  string planenamelist;
-  DBRequest list[]={
-    {"dc_num_planes",&fNPlanes, kInt},
-    {"dc_num_chambers",&fNChambers, kInt},
-    {"dc_tdc_time_per_channel",&fNSperChan, kDouble},
-    {"dc_wire_velocity",&fWireVelocity,kDouble},
-    {"dc_plane_names",&planenamelist, kString},
-    {0}
-  };
-
-  gHcParms->LoadParmValues((DBRequest*)&list,prefix);
-  cout << planenamelist << endl;
-  cout << "Drift Chambers: " <<  fNPlanes << " planes in " << fNChambers << " chambers" << endl;
-
-  vector<string> plane_names = vsplit(planenamelist);
-
-  if(plane_names.size() != (UInt_t) fNPlanes) {
-    cout << "ERROR: Number of planes " << fNPlanes << " doesn't agree with number of plane names " << plane_names.size() << endl;
-    // Should quit.  Is there an official way to quit?
-  }
-  fPlaneNames = new char* [fNPlanes];
-  for(Int_t i=0;i<fNPlanes;i++) {
-    fPlaneNames[i] = new char[plane_names[i].length()];
-    strcpy(fPlaneNames[i], plane_names[i].c_str());
-  }
-
-  char *desc = new char[strlen(description)+100];
-  fPlanes = new THcDriftChamberPlane* [fNPlanes];
-
-  for(Int_t i=0;i<fNPlanes;i++) {
-    strcpy(desc, description);
-    strcat(desc, " Plane ");
-    strcat(desc, fPlaneNames[i]);
-
-    fPlanes[i] = new THcDriftChamberPlane(fPlaneNames[i], desc, i+1, this);
-    cout << "Created Drift Chamber Plane " << fPlaneNames[i] << ", " << desc << endl;
-
-  }
-    
 }
 
 //_____________________________________________________________________________
 THcDriftChamber::THcDriftChamber( ) :
-  THaTrackingDetector()
+  THaSubDetector()
 {
   // Constructor
 }
 
+//_____________________________________________________________________________
+Int_t THcDriftChamber::Decode( const THaEvData& evdata )
+{
+  cout << "THcDriftChamber::Decode called" << endl;
+  return 0;
+}
+
 //_____________________________________________________________________________
 THaAnalysisObject::EStatus THcDriftChamber::Init( const TDatime& date )
 {
   static const char* const here = "Init()";
 
-  Setup(GetName(), GetTitle());	// Create the subdetectors here
+  Setup(GetName(), GetTitle());
   
-  // Should probably put this in ReadDatabase as we will know the
-  // maximum number of hits after setting up the detector map
-  THcHitList::InitHitList(fDetMap, "THcRawDCHit", 1000);
-
   EStatus status;
   // This triggers call of ReadDatabase and DefineVariables
-  if( (status = THaTrackingDetector::Init( date )) )
+  if( (status = THaSubDetector::Init( date )) )
     return fStatus=status;
 
-  for(Int_t ip=0;ip<fNPlanes;ip++) {
-    if((status = fPlanes[ip]->Init( date ))) {
-      return fStatus=status;
-    }
-  }
-
-  // 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) );
-
-  // Will need to determine which apparatus it belongs to and use the
-  // appropriate detector ID in the FillMap call
-  char EngineDID[4];
+  return fStatus = kOK;
+}
 
-  EngineDID[0] = toupper(GetApparatus()->GetName()[0]);
-  EngineDID[1] = 'D';
-  EngineDID[2] = 'C';
-  EngineDID[3] = '\0';
-  
-  if( gHcDetectorMap->FillMap(fDetMap, EngineDID) < 0 ) {
-    Error( Here(here), "Error filling detectormap for %s.", 
-	     EngineDID);
-      return kInitError;
+void THcDriftChamber::AddPlane(THcDriftChamberPlane *plane)
+{
+  cout << "Added plane " << plane->GetPlaneNum() << " to chamber " << fChamberNum << endl;
+  plane->SetPlaneIndex(fNPlanes);
+  fPlanes[fNPlanes] = plane;
+
+  // HMS Specific
+  // Check if this is a Y Plane
+  if(plane->GetPlaneNum() == YPlaneNum) {
+    YPlaneInd = fNPlanes;
+  } else if (plane->GetPlaneNum() == YPlanePNum) {
+    YPlanePInd = fNPlanes;
   }
+  fNPlanes++;
 
-  return fStatus = kOK;
+  return;
 }
 
 //_____________________________________________________________________________
 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()";
+  cout << "THcDriftChamber::ReadDatabase()" << endl;
   char prefix[2];
-  char parname[100];
-
-  // Read data from database 
-  // Pull values from the THcParmList instead of reading a database
-  // file like Hall A does.
-
-  // 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)
-
   prefix[0]=tolower(GetApparatus()->GetName()[0]);
-
   prefix[1]='\0';
-
-  fXCenter = new Double_t [fNChambers];
-  fYCenter = new Double_t [fNChambers];
-
-  fTdcWinMin = new Int_t [fNPlanes];
-  fTdcWinMax = new Int_t [fNPlanes];
-  fCentralTime = new Int_t [fNPlanes];
-  fNWires = new Int_t [fNPlanes];
-  fNChamber = new Int_t [fNPlanes]; // Which chamber is this plane
-  fWireOrder = new Int_t [fNPlanes]; // Wire readout order
-  fDriftTimeSign = new Int_t [fNPlanes];
-
-  fZPos = new Double_t [fNPlanes];
-  fAlphaAngle = new Double_t [fNPlanes];
-  fBetaAngle = new Double_t [fNPlanes];
-  fGammaAngle = new Double_t [fNPlanes];
-  fPitch = new Double_t [fNPlanes];
-  fCentralWire = new Double_t [fNPlanes];
-  fPlaneTimeZero = new Double_t [fNPlanes];
-
-
   DBRequest list[]={
-    {"dc_tdc_time_per_channel",&fNSperChan, kDouble},
-    {"dc_wire_velocity",&fWireVelocity,kDouble},
-
-    {"dc_xcenter", fXCenter, kDouble, fNChambers},
-    {"dc_ycenter", fYCenter, kDouble, fNChambers},
-
-    {"dc_tdc_min_win", fTdcWinMin, kInt, fNPlanes},
-    {"dc_tdc_max_win", fTdcWinMax, kInt, fNPlanes},
-    {"dc_central_time", fCentralTime, kInt, fNPlanes},
-    {"dc_nrwire", fNWires, kInt, fNPlanes},
-    {"dc_chamber_planes", fNChamber, kInt, fNPlanes},
-    {"dc_wire_counting", fWireOrder, kInt, fNPlanes},
-    {"dc_drifttime_sign", fDriftTimeSign, kInt, fNPlanes},
-
-    {"dc_zpos", fZPos, kDouble, fNPlanes},
-    {"dc_alpha_angle", fAlphaAngle, kDouble, fNPlanes},
-    {"dc_beta_angle", fBetaAngle, kDouble, fNPlanes},
-    {"dc_gamma_angle", fGammaAngle, kDouble, fNPlanes},
-    {"dc_pitch", fPitch, kDouble, fNPlanes},
-    {"dc_central_wire", fCentralWire, kDouble, fNPlanes},
-    {"dc_plane_time_zero", fPlaneTimeZero, kDouble, fNPlanes},
+    {"_remove_sppt_if_one_y_plane",&fRemove_Sppt_If_One_YPlane, kInt},
     {0}
   };
   gHcParms->LoadParmValues((DBRequest*)&list,prefix);
 
-  cout << "Plane counts:";
-  for(Int_t i=0;i<fNPlanes;i++) {
-    cout << " " << fNWires[i];
-  }
-  cout << endl;
+  // Get parameters parent knows about
+  THcDC* fParent;
+  fParent = (THcDC*) GetParent();
+  fMinHits = fParent->GetMinHits(fChamberNum);
+  fMaxHits = fParent->GetMaxHits(fChamberNum);
+  fMinCombos = fParent->GetMinCombos(fChamberNum);
 
-  fIsInit = true;
+  cout << "Chamber " << fChamberNum << "  Min/Max: " << fMinHits << "/" << fMaxHits << endl;
 
+  fSpacePointCriterion = fParent->GetSpacePointCriterion(fChamberNum); 
+  fSpacePointCriterion2 = fSpacePointCriterion*fSpacePointCriterion;
+
+  // HMS Specific
+  // Hard code Y plane numbers.  Should be able to get from wire angle
+  if(fChamberNum == 1) {
+    YPlaneNum = 2;
+    YPlanePNum = 5;
+  } else {
+    YPlaneNum = 8;
+    YPlanePNum = 11;
+  }
+    
+  fIsInit = true;
   return kOK;
 }
 
@@ -249,165 +160,607 @@ Int_t THcDriftChamber::DefineVariables( EMode mode )
   // 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" },
+  //    { "nhit", "Number of DC hits",  "fNhits" },
   //    { 0 }
   //  };
   //  return DefineVarsFromList( vars, mode );
   return kOK;
-}
 
-//_____________________________________________________________________________
-THcDriftChamber::~THcDriftChamber()
+}
+void THcDriftChamber::ProcessHits( void)
 {
-  // Destructor. Remove variables from global list.
+  // Make a list of hits for whole chamber
+  fNhits = 0;
 
-  if( fIsSetup )
-    RemoveVariables();
-  if( fIsInit )
-    DeleteArrays();
-  if (fTrackProj) {
-    fTrackProj->Clear();
-    delete fTrackProj; fTrackProj = 0;
+  for(Int_t ip=0;ip<fNPlanes;ip++) {
+    TClonesArray* hitsarray = fPlanes[ip]->GetHits();
+    for(Int_t ihit=0;ihit<fPlanes[ip]->GetNHits();ihit++) {
+      fHits[fNhits++] = static_cast<THcDCHit*>(hitsarray->At(ihit));
+    }
   }
+  //  cout << "ThcDriftChamber::ProcessHits() " << fNhits << " hits" << endl;
 }
 
-//_____________________________________________________________________________
-void THcDriftChamber::DeleteArrays()
+
+Int_t THcDriftChamber::FindSpacePoints( void )
 {
-  // Delete member arrays. Used by destructor.
+  // Following h_pattern_recognition.f, but just for one chamber
 
-  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;
+  // Code below is specifically for HMS chambers with Y and Y' planes
+
+  Int_t yplane_hitind=0;
+  Int_t yplanep_hitind=0;
+
+  fNSpacePoints=0;
+  fEasySpacePoint = 0;
+  // Should really build up array of hits
+  if(fNhits >= fMinHits && fNhits < fMaxHits) {
+    /* Has this list of hits already been cut the way it should have at this point? */
+    
+    for(Int_t ihit=0;ihit<fNhits;ihit++) {
+      THcDCHit* thishit = fHits[ihit];
+      Int_t ip=thishit->GetPlaneNum();  // This is the absolute plane mumber
+      if(ip==YPlaneNum) yplane_hitind = ihit;
+      if(ip==YPlanePNum) yplanep_hitind = ihit;
+    }
+    // fPlanes is the array of planes for this chamber.
+    //    cout << fPlanes[YPlaneInd]->GetNHits() << " "
+    //	 << fPlanes[YPlanePInd]->GetNHits() << " " << endl;
+    if (fPlanes[YPlaneInd]->GetNHits() == 1 && fPlanes[YPlanePInd]->GetNHits() == 1) {
+      cout << fHits[yplane_hitind]->GetWireNum() << " "
+	   << fHits[yplane_hitind]->GetPos() << " "
+	   << fHits[yplanep_hitind]->GetWireNum() << " "
+	   << fHits[yplanep_hitind]->GetPos() << " " 
+	   << fSpacePointCriterion << endl;
+    }
+    if(fPlanes[YPlaneInd]->GetNHits() == 1 && fPlanes[YPlanePInd]->GetNHits() == 1
+       && TMath::Abs(fHits[yplane_hitind]->GetPos() - fHits[yplanep_hitind]->GetPos())
+       < fSpacePointCriterion
+       && fNhits <= 6) {	// An easy case, probably one hit per plane
+      fEasySpacePoint = FindEasySpacePoint(yplane_hitind, yplanep_hitind);
+    }
+    if(!fEasySpacePoint) {	// It's not easy
+      FindHardSpacePoints();
+    }
+
+    // We have our space points for this chamber
+    cout << fNSpacePoints << " Space Points found" << endl;
+    if(fNSpacePoints > 0) {
+      if(fRemove_Sppt_If_One_YPlane == 1) {
+	// The routine is specific to HMS
+	Int_t ndest=DestroyPoorSpacePoints();
+	cout << ndest << " Poor space points destroyed" << endl;
+	// Loop over space points and remove those with less than 4 planes
+	// hit and missing hits in Y,Y' planes
+      }
+      if(fNSpacePoints == 0) cout << "DestroyPoorSpacePoints() killed SP" << endl;
+      Int_t nadded=SpacePointMultiWire();
+      if (nadded) cout << nadded << " Space Points added with SpacePointMultiWire()" << endl;
+      ChooseSingleHit();
+      SelectSpacePoints();
+      if(fNSpacePoints == 0) cout << "SelectSpacePoints() killed SP" << endl;
+    }
+    //cout << fNSpacePoints << " Space Points remain" << endl;
+    // Add these space points to the total list of space points for the
+    // the DC package.  Do this in THcDC.cxx.
+#if 0
+    for(Int_t ip=0;ip<fNPlanes;ip++) {
+      Int_t np = fPlanes[ip]->GetPlaneNum(); // Actuall plane number of this plane
+      // (0-11) or (1-12)?
+      TClonesArray* fHits = fPlanes[ip]->GetHits();
+
+      for(Int_t ihit=0;ihit<fNhits;ihit++) { // Looping over all hits in all planes of the chamber
+	THcDCHit* hit = static_cast<THcDCHit*>(fHits->At(ihit));
+	// 
+
+      }
+    }
+#endif
+  }
+  return(fNSpacePoints);
 }
 
 //_____________________________________________________________________________
-inline 
-void THcDriftChamber::ClearEvent()
+// HMS Specific
+Int_t THcDriftChamber::FindEasySpacePoint(Int_t yplane_hitind,Int_t yplanep_hitind)
 {
-  // Reset per-event data.
+  // Simplified HMS find_space_point routing.  It is given all y hits and
+  // checks to see if all x-like hits are close enough together to make
+  // a space point.
+
+  Int_t easy_space_point=0;
+  cout << "Doing Find Easy Space Point" << endl;
+  Double_t yt = (fHits[yplane_hitind]->GetPos() + fHits[yplanep_hitind]->GetPos())/2.0;
+  Double_t xt = 0.0;
+  Int_t num_xhits = 0;
+  Double_t x_pos[MAX_HITS_PER_POINT];
+
+  for(Int_t ihit=0;ihit<fNhits;ihit++) {
+    THcDCHit* thishit = fHits[ihit];
+    if(ihit!=yplane_hitind && ihit!=yplanep_hitind) { // x-like hit
+      // ysp and xsp are from h_generate_geometry
+      x_pos[ihit] = (thishit->GetPos()
+		     -yt*thishit->GetWirePlane()->GetYsp())
+	/thishit->GetWirePlane()->GetXsp();
+      xt += x_pos[ihit];
+      num_xhits++;
+    } else {
+      x_pos[ihit] = 0.0;
+    }
+  }
+  xt = (num_xhits>0?xt/num_xhits:0.0);
+  cout << "xt=" << xt << endl;
+  easy_space_point = 1; // Assume we have an easy space point
+  // Rule it out if x points don't cluster well enough
+  for(Int_t ihit=0;ihit<fNhits;ihit++) {
+    cout << "Hit " << ihit << " " << x_pos[ihit] << " " << xt << endl;
+    if(ihit!=yplane_hitind && ihit!=yplanep_hitind) { // x-like hit
+      if(TMath::Abs(xt-x_pos[ihit]) >= fSpacePointCriterion)
+	{ easy_space_point=0; break;}
+    }
+  }
+  if(easy_space_point) {	// Register the space point
+    cout << "Easy Space Point " << xt << " " << yt << endl;
+    fNSpacePoints = 1;
+    fSpacePoints[0].x = xt;
+    fSpacePoints[0].y = yt;
+    fSpacePoints[0].nhits = fNhits;
+    fSpacePoints[0].ncombos = 0; // No combos
+    for(Int_t ihit=0;ihit<fNhits;ihit++) {
+      THcDCHit* thishit = fHits[ihit];
+      fSpacePoints[0].hits[ihit] = thishit;
+    }
+  }
+  return(easy_space_point);
+}
 
-  fTrackProj->Clear();
+//_____________________________________________________________________________
+// Generic
+Int_t THcDriftChamber::FindHardSpacePoints()
+{
+  Int_t MAX_NUMBER_PAIRS=1000; // Where does this get set?
+  struct Pair {
+    THcDCHit* hit1;
+    THcDCHit* hit2;
+    Double_t x, y;
+  };
+  Pair pairs[MAX_NUMBER_PAIRS];
+  //	
+  Int_t ntest_points=0;
+  for(Int_t ihit1=0;ihit1<fNhits-1;ihit1++) {
+    THcDCHit* hit1=fHits[ihit1];
+    THcDriftChamberPlane* plane1 = hit1->GetWirePlane();
+    for(Int_t ihit2=ihit1+1;ihit2<fNhits;ihit2++) {
+      if(ntest_points < MAX_NUMBER_PAIRS) {
+	THcDCHit* hit2=fHits[ihit2];
+	THcDriftChamberPlane* plane2 = hit2->GetWirePlane();
+	Double_t determinate = plane1->GetXsp()*plane2->GetYsp()
+	  -plane1->GetYsp()*plane2->GetXsp();
+	if(TMath::Abs(determinate) > 0.3) { // 0.3 is sin(alpha1-alpha2)=sin(17.5)
+	  pairs[ntest_points].hit1 = hit1;
+	  pairs[ntest_points].hit2 = hit2;
+	  pairs[ntest_points].x = (hit1->GetPos()*plane2->GetYsp()
+				   - hit2->GetPos()*plane1->GetYsp())
+	    /determinate;
+	  pairs[ntest_points].y = (hit2->GetPos()*plane1->GetXsp()
+				   - hit1->GetPos()*plane2->GetXsp())
+	    /determinate;
+	  ntest_points++;
+	}
+      }
+    }
+  }
+  Int_t ncombos=0;
+  struct Combo {
+    Pair* pair1;
+    Pair* pair2;
+  };
+  Combo combos[10*MAX_NUMBER_PAIRS];
+  for(Int_t ipair1=0;ipair1<ntest_points-1;ipair1++) {
+    for(Int_t ipair2=ipair1+1;ipair2<ntest_points;ipair2++) {
+      Double_t dist2 = pow(pairs[ipair1].x - pairs[ipair2].x,2)
+	+ pow(pairs[ipair1].y - pairs[ipair2].y,2);
+      if(dist2 <= fSpacePointCriterion2) {
+	combos[ncombos].pair1 = &pairs[ipair1];
+	combos[ncombos].pair2 = &pairs[ipair2];
+	ncombos++;
+      }
+    }
+  }
+  // Loop over all valid combinations and build space points
+  for(Int_t icombo=0;icombo<ncombos;icombo++) {
+    THcDCHit* hits[4];
+    hits[0]=combos[icombo].pair1->hit1;
+    hits[1]=combos[icombo].pair1->hit2;
+    hits[2]=combos[icombo].pair2->hit1;
+    hits[3]=combos[icombo].pair2->hit2;
+    // Get Average Space point xt, yt
+    Double_t xt = combos[icombo].pair1->x + combos[icombo].pair2->x;
+    Double_t yt = combos[icombo].pair1->y + combos[icombo].pair2->y;
+    // Loop over space points
+    if(fNSpacePoints > 0) {
+      Int_t add_flag=1;
+      for(Int_t ispace=0;ispace<fNSpacePoints;ispace++) {
+	if(fSpacePoints[ispace].nhits > 0) {
+	  Double_t sqdist_test = pow(xt - fSpacePoints[ispace].x,2) +
+	    pow(yt - fSpacePoints[ispace].y,2);
+	  // I (who is I) want to be careful if sqdist_test is bvetween 1 and
+	  // 3 fSpacePointCriterion2.  Let me ignore not add a new point the
+	  if(sqdist_test < 3*fSpacePointCriterion2) {
+	    add_flag = 0;	// do not add a new space point
+	  }
+	  if(sqdist_test < fSpacePointCriterion2) {
+	    // This is a real match
+	    // Add the new hits to the existing space point
+	    Int_t iflag[4];
+	    iflag[0]=0;iflag[1]=0;iflag[2]=0;iflag[3]=0;
+	    // Find out which of the four hits in the combo are already
+	    // in the space point under consideration so that we don't
+	    // add duplicate hits to the space point
+	    for(Int_t isp_hit=0;isp_hit<fSpacePoints[ispace].nhits;isp_hit++) {
+	      for(Int_t icm_hit=0;icm_hit<4;icm_hit++) { // Loop over combo hits
+		if(fSpacePoints[ispace].hits[isp_hit]==hits[icm_hit]) {
+		  iflag[icm_hit] = 1;
+		}
+	      }
+	    }
+	    // Remove duplicated pionts in the combo so we don't add
+	    // duplicate hits to the space point
+	    for(Int_t icm1=0;icm1<3;icm1++) {
+	      for(Int_t icm2=icm1+1;icm2<4;icm2++) {
+		if(hits[icm1]==hits[icm2]) {
+		  iflag[icm2] = 1;
+		}
+	      }
+	    }
+	    // Add the unique combo hits to the space point
+	    for(Int_t icm=0;icm<4;icm++) {
+	      if(iflag[icm]==0) {
+		fSpacePoints[ispace].hits[fSpacePoints[ispace].nhits++] = hits[icm];
+	      }
+	      fSpacePoints[ispace].ncombos++;
+	    }
+	  }
+	}
+      }// End of loop over existing space points
+      // Create a new space point if more than 2*space_point_criteria
+      if(fNSpacePoints < MAX_SPACE_POINTS) {
+	if(add_flag) {
+	  fSpacePoints[fNSpacePoints].nhits=2;
+	  fSpacePoints[fNSpacePoints].ncombos=1;
+	  fSpacePoints[fNSpacePoints].hits[0]=hits[0];
+	  fSpacePoints[fNSpacePoints].hits[1]=hits[1];
+	  fSpacePoints[fNSpacePoints].x = xt;
+	  fSpacePoints[fNSpacePoints].y = yt;
+	  if(hits[0] != hits[2] && hits[1] != hits[2]) {
+	    fSpacePoints[fNSpacePoints].hits[fSpacePoints[fNSpacePoints].nhits++] = hits[2];
+	  }
+	  if(hits[0] != hits[3] && hits[1] != hits[3]) {
+	    fSpacePoints[fNSpacePoints].hits[fSpacePoints[fNSpacePoints].nhits++] = hits[3];
+	  }
+	  fNSpacePoints++;
+	}
+      }
+    } else {// Create first space point
+      // This duplicates code above.  Need to see if we can restructure
+      // to avoid
+      fSpacePoints[fNSpacePoints].nhits=2;
+      fSpacePoints[fNSpacePoints].ncombos=1;
+      fSpacePoints[fNSpacePoints].hits[0]=hits[0];
+      fSpacePoints[fNSpacePoints].hits[1]=hits[1];
+      fSpacePoints[fNSpacePoints].x = xt;
+      fSpacePoints[fNSpacePoints].y = yt;
+      if(hits[0] != hits[2] && hits[1] != hits[2]) {
+	fSpacePoints[fNSpacePoints].hits[fSpacePoints[fNSpacePoints].nhits++] = hits[2];
+      }
+      if(hits[0] != hits[3] && hits[1] != hits[3]) {
+	fSpacePoints[fNSpacePoints].hits[fSpacePoints[fNSpacePoints].nhits++] = hits[3];
+      }
+      fNSpacePoints++;
+    }//End check on 0 space points
+  }//End loop over combos
+  return(fNSpacePoints);
 }
 
 //_____________________________________________________________________________
-Int_t THcDriftChamber::Decode( const THaEvData& evdata )
+// HMS Specific?
+Int_t THcDriftChamber::DestroyPoorSpacePoints()
 {
+  Int_t nhitsperplane[fNPlanes];
 
-  // Get the Hall C style hitlist (fRawHitList) for this event
-  Int_t nhits = THcHitList::DecodeToHitList(evdata);
+  Int_t spacepointsgood[fNSpacePoints];
+  Int_t ngood=0;
 
-  // Let each plane get its hits
-  Int_t nexthit = 0;
-  for(Int_t ip=0;ip<fNPlanes;ip++) {
-    nexthit = fPlanes[ip]->ProcessHits(fRawHitList, nexthit);
+  for(Int_t i=0;i<fNSpacePoints;i++) {
+    spacepointsgood[i] = 0;
+  }
+  for(Int_t isp=0;isp<fNSpacePoints;isp++) {
+    Int_t nplanes_hit = 0;
+    for(Int_t ip=0;ip<fNPlanes;ip++) {
+      nhitsperplane[ip] = 0;
+    }
+    // Count # hits in each plane for this space point
+    for(Int_t ihit=0;ihit<fSpacePoints[isp].nhits;ihit++) {
+      THcDCHit* hit=fSpacePoints[isp].hits[ihit];
+      // hit_order(hit) = ihit;
+      Int_t ip = hit->GetPlaneIndex();
+      nhitsperplane[ip]++;
+    }
+    // Count # planes that have hits
+    for(Int_t ip=0;ip<fNPlanes;ip++) {
+      if(nhitsperplane[ip] > 0) {
+	nplanes_hit++;
+      }
+    }
+    if(nplanes_hit >= fMinHits && nhitsperplane[YPlaneInd]>0
+       && nhitsperplane[YPlanePInd] > 0) {
+      spacepointsgood[ngood++] = isp; // Build list of good points
+    } else {
+      //      cout << "Missing Y-hit!!";
+    }
   }
 
-#if 0
-  // fRawHitList is TClones array of THcRawDCHit objects
-  for(Int_t ihit = 0; ihit < fNRawHits ; ihit++) {
-    THcRawDCHit* hit = (THcRawDCHit *) 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;
+  // Remove the bad space points
+  Int_t nremoved=fNSpacePoints-ngood;
+  fNSpacePoints = ngood;
+  for(Int_t isp=0;isp<fNSpacePoints;isp++) { // New index num ber
+    Int_t osp=spacepointsgood[isp]; // Original index number
+    if(osp > isp) {
+      // Does this work, or do we have to copy each member?
+      // If it doesn't we should overload the = operator
+      fSpacePoints[isp] = fSpacePoints[osp];
     }
   }
-  //  cout << endl;
+  return nremoved;
+}
+    
+//_____________________________________________________________________________
+// HMS Specific?
+  /*
+   Purpose and Methods :  This routine loops over space points and 
+                          looks at all hits in the space
+                          point. If more than 1 hit is in the same 
+                          plane then the space point is cloned with
+                          all combinations of 1 wire per plane.  The 
+                          requirements for cloning are:  1) at least 
+                          4 planes fire, and 2) no more than 6 planes 
+                          have multiple hits.      
+  */
+Int_t THcDriftChamber::SpacePointMultiWire()
+{
+  Int_t nhitsperplane[fNPlanes];
+  THcDCHit* hits_plane[fNPlanes][MAX_HITS_PER_POINT];
+
+  Int_t nsp_check;
+  Int_t nplanes_single;
+
+  Int_t nsp_tot=fNSpacePoints;
+
+  for(Int_t isp=0;isp<fNSpacePoints;isp++) {
+    Int_t nplanes_hit = 0;	// Number of planes with hits
+    Int_t nplanes_mult = 0;	// Number of planes with multiple hits
+    Int_t nsp_new = 1;
+    Int_t newsp_num=0;
+
+    for(Int_t ip=0;ip<fNPlanes;ip++) {
+      nhitsperplane[ip] = 0;
+    }
+    // Sort Space Points hits by plane
+    for(Int_t ihit=0;ihit<fSpacePoints[isp].nhits;ihit++) { // All hits in SP
+      THcDCHit* hit=fSpacePoints[isp].hits[ihit];
+      //      hit_order Make a hash
+      // hash(hit) = ihit;
+      Int_t ip = hit->GetPlaneIndex();
+      hits_plane[ip][nhitsperplane[ip]++] = hit;
+    }
+    for(Int_t ip=0;ip<fNPlanes;ip++) {
+      if(nhitsperplane[ip] > 0) {
+	nplanes_hit++;
+	nsp_new *= nhitsperplane[ip];
+	if(nhitsperplane[ip] > 1) nplanes_mult++;
+      }
+    }
+    --nsp_new;
+    nsp_check=nsp_tot + nsp_new;
+    nplanes_single = nplanes_hit - nplanes_mult;
+    
+    // Check if cloning conditions are met
+    Int_t ntot = 0;
+    if(nplanes_hit >= 4 && nplanes_mult < 4 && nplanes_mult >0
+       && nsp_check < 20) {
+      
+      // Order planes by decreasing # of hits
+      
+      Int_t maxplane[fNPlanes];
+      for(Int_t ip=0;ip<fNPlanes;ip++) {
+	maxplane[ip] = ip;
+      }
+      // Sort by decreasing # of hits
+      for(Int_t ip1=0;ip1<fNPlanes-1;ip1++) {
+	for(Int_t ip2=ip1+1;ip2<fNPlanes;ip2++) {
+	  if(nhitsperplane[maxplane[ip2]] > nhitsperplane[maxplane[ip1]]) {
+	    Int_t temp = maxplane[ip1];
+	    maxplane[ip1] = maxplane[ip2];
+	    maxplane[ip2] = temp;
+	  }
+	}
+      }
+
+      // First fill clones with 1 hit each from the 3 planes with the most hits
+      for(Int_t n1=0;n1<nhitsperplane[maxplane[0]];n1++) {
+	for(Int_t n2=0;n2<nhitsperplane[maxplane[1]];n2++) {
+	  for(Int_t n3=0;n3<nhitsperplane[maxplane[2]];n3++) {
+	    ntot++;
+	    newsp_num = nsp_tot + ntot - 2; // ntot will be 2 for first new
+	    if(n1==0 && n2==0 && n3==0) newsp_num = isp; // Copy over original SP
+	    fSpacePoints[newsp_num].x = fSpacePoints[isp].x;
+	    fSpacePoints[newsp_num].y = fSpacePoints[isp].y;
+	    fSpacePoints[newsp_num].nhits = nplanes_hit;
+	    fSpacePoints[newsp_num].ncombos = fSpacePoints[isp].ncombos;
+	    fSpacePoints[newsp_num].hits[0] = hits_plane[maxplane[0]][n1];
+	    fSpacePoints[newsp_num].hits[1] = hits_plane[maxplane[1]][n2];
+	    fSpacePoints[newsp_num].hits[2] = hits_plane[maxplane[2]][n3];
+	    fSpacePoints[newsp_num].hits[3] = hits_plane[maxplane[3]][0];
+	    if(nhitsperplane[maxplane[4]] == 1)
+	      fSpacePoints[newsp_num].hits[4] = hits_plane[maxplane[4]][0];
+	    if(nhitsperplane[maxplane[5]] == 1)
+	      fSpacePoints[newsp_num].hits[5] = hits_plane[maxplane[5]][0];
+	  }
+	}
+      }
+#if 0
+      // Loop over clones and order hits in the same way as parent SP
+      // Why do we have to order the hits.
+      for(Int_t i=0;i<ntot;i++) {
+	Int_t newsp_num= nsp_tot + i;
+	if(i == 1) newsp_num = isp;
+	for(Int_t j=0;j<nplanes_hit;j++) {
+	  for(Int_t k=0;k<nplanes_hit;k++) {
+	    THcDCHit* hit1 = fSpacePointHits[newsp_num][j];
+	    THcDCHit* hit2 = fSpacePointHits[newsp_num][k];
+	    if(hit_order(hit1) > hit_order(hit2)) {
+	      THcDCHit* temp = fSpacePoints[newsp_num].hits[k];
+	      fSpacePoints[newsp_num].hits[k] = fSpacePoints[newsp_num].hits[j];
+	      fSpacePoints[newsp_num].hits[j] = temp;
+	    }
+	  }
+	}
+      }
 #endif
+      nsp_tot += (ntot-1);
+    } else {
+      ntot=1;
+    }
+  }
+  assert (nsp_tot > 0);
+  Int_t nadded=0;
+  if(nsp_tot <= 20) {
+    nadded = nsp_tot - fNSpacePoints;
+    fNSpacePoints = nsp_tot;
+  }
 
-  return nhits;
+  // In Fortran, fill in zeros.
+  return(nadded);
 }
 
 //_____________________________________________________________________________
-Int_t THcDriftChamber::ApplyCorrections( void )
+// HMS Specific?
+void THcDriftChamber::ChooseSingleHit()
 {
-  return(0);
+  // Look at all hits in a space point.  If two hits are in the same plane,
+  // reject the one with the longer drift time.
+  Int_t goodhit[MAX_HITS_PER_POINT];
+
+  for(Int_t isp=0;isp<fNSpacePoints;isp++) {
+    Int_t startnum = fSpacePoints[isp].nhits;
+    
+    for(Int_t ihit=0;ihit<startnum;ihit++) {
+      goodhit[ihit] = 1;
+    }
+    // For each plane, mark all hits longer than the shortest drift time
+    for(Int_t ihit1=0;ihit1<startnum-1;ihit1++) {
+      THcDCHit* hit1 = fSpacePoints[isp].hits[ihit1];
+      Int_t plane1=hit1->GetPlaneIndex();
+      Double_t tdrift1 = hit1->GetTime();
+      for(Int_t ihit2=ihit1+1;ihit2<startnum;ihit2++) {
+	THcDCHit* hit2 = fSpacePoints[isp].hits[ihit2];
+	Int_t plane2=hit2->GetPlaneIndex();
+	Double_t tdrift2 = hit2->GetTime();
+	if(plane1 == plane2) {
+	  if(tdrift1 > tdrift2) {
+	    goodhit[ihit1] = 0;
+	  } else {
+	    goodhit[ihit2] = 0;
+	  }
+	}
+      }
+    }
+    // Gather the remaining hits
+    Int_t finalnum = 0;
+    for(Int_t ihit=0;ihit<startnum;ihit++) {
+      if(goodhit[ihit] > 0) {	// Keep this hit
+	if (ihit > finalnum) {	// Move hit 
+	  fSpacePoints[isp].hits[finalnum++] = fSpacePoints[isp].hits[ihit];
+	} else {
+	  finalnum++;
+	}
+      }
+    }
+    fSpacePoints[isp].nhits = finalnum;
+  }
 }
+//_____________________________________________________________________________
+// Generic
+void THcDriftChamber::SelectSpacePoints()
+//    This routine goes through the list of space_points and space_point_hits
+//    found by find_space_points and only accepts those with 
+//    number of hits > min_hits
+//    number of combinations > min_combos
+{
+  Int_t sp_count=0;
+  for(Int_t isp=0;isp<fNSpacePoints;isp++) {
+    // Include fEasySpacePoint because ncombos not filled in
+    if(fSpacePoints[isp].ncombos >= fMinCombos || fEasySpacePoint) {
+      if(fSpacePoints[isp].nhits >= fMinHits) {
+	fSpacePoints[sp_count++] = fSpacePoints[isp];
+      }
+    }
+  }
+  fNSpacePoints = sp_count;
+}
+
+/*
+*
+* Now we know rough hit positions in the chambers so we can make
+* wire velocity drift time corrections for each hit in the space point
+*
+* Assume all wires for a plane are read out on the same side (l/r or t/b).
+* If the wire is closer to horizontal, read out left/right.  If nearer
+* vertical, assume top/bottom.  (Note, this is not always true for the
+* SOS u and v planes.  They have 1 card each on the side, but the overall
+* time offset per card will cancel much of the error caused by this.  The
+* alternative is to check by card, rather than by plane and this is harder.
+*/
+
 
 //_____________________________________________________________________________
-Int_t THcDriftChamber::CoarseTrack( TClonesArray& /* tracks */ )
+THcDriftChamber::~THcDriftChamber()
 {
-  // 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();
+  // Destructor. Remove variables from global list.
 
-  return 0;
+  if( fIsSetup )
+    RemoveVariables();
+  if( fIsInit )
+    DeleteArrays();
+  if (fTrackProj) {
+    fTrackProj->Clear();
+    delete fTrackProj; fTrackProj = 0;
+  }
 }
 
 //_____________________________________________________________________________
-Int_t THcDriftChamber::FineTrack( TClonesArray& tracks )
+void THcDriftChamber::DeleteArrays()
 {
-  // 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.
+  // Delete member arrays. Used by destructor.
 
-  // 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;
+//_____________________________________________________________________________
+inline 
+void THcDriftChamber::Clear( const Option_t* )
+{
+  // Reset per-event data.
+  //  fNhits = 0;
+
+  //  fTrackProj->Clear();
+  fNhits = 0;
+
+}
+
+//_____________________________________________________________________________
+Int_t THcDriftChamber::ApplyCorrections( void )
+{
+  return(0);
 }
 
 ClassImp(THcDriftChamber)
diff --git a/src/THcDriftChamber.h b/src/THcDriftChamber.h
index a973c466a25804993d2e8c3576d05cefd9c1eb56..96c293c0fbe4c6a7600a712c3a907a804cc0413f 100644
--- a/src/THcDriftChamber.h
+++ b/src/THcDriftChamber.h
@@ -7,52 +7,40 @@
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
-#include "THaTrackingDetector.h"
-#include "THcHitList.h"
-#include "THcRawDCHit.h"
+#include "THaSubDetector.h"
 #include "THcDriftChamberPlane.h"
-#include "TMath.h"
+#include "TClonesArray.h"
+
+#define MAX_SPACE_POINTS 50
+#define MAX_HITS_PER_POINT 20
+
+//#include "TMath.h"
 
 //class THaScCalib;
 class TClonesArray;
 
-class THcDriftChamber : public THaTrackingDetector, public THcHitList {
+class THcDriftChamber : public THaSubDetector {
 
 public:
-  THcDriftChamber( const char* name, const char* description = "",
-		   THaApparatus* a = NULL );
+  THcDriftChamber( const char* name, const char* description, Int_t chambernum,
+		   THaDetectorBase* parent = NULL );
   virtual ~THcDriftChamber();
 
-  virtual Int_t      Decode( const THaEvData& );
+  virtual Int_t Decode( const THaEvData& );
   virtual EStatus    Init( const TDatime& run_time );
-  virtual Int_t      CoarseTrack( TClonesArray& tracks );
-  virtual Int_t      FineTrack( TClonesArray& tracks );
   
+  virtual void       AddPlane(THcDriftChamberPlane *plane);
   virtual Int_t      ApplyCorrections( void );
+  virtual void       ProcessHits( void );
+  virtual Int_t      FindSpacePoints( void ) ;
+
+  virtual void   Clear( Option_t* opt="" );
 
   //  Int_t GetNHits() const { return fNhit; }
   
   Int_t GetNTracks() const { return fTrackProj->GetLast()+1; }
   const TClonesArray* GetTrackHits() const { return fTrackProj; }
 
-  Int_t GetNWires(Int_t plane) const { return fNWires[plane-1];}
-  Int_t GetNChamber(Int_t plane) const { return fNChamber[plane-1];}
-  Int_t GetWireOrder(Int_t plane) const { return fWireOrder[plane-1];}
-  Int_t GetPitch(Int_t plane) const { return fPitch[plane-1];}
-  Int_t GetCentralWire(Int_t plane) const { return fCentralWire[plane-1];}
-  Int_t GetTdcWinMin(Int_t plane) const { return fTdcWinMin[plane-1];}
-  Int_t GetTdcWinMax(Int_t plane) const { return fTdcWinMax[plane-1];}
-
-  Double_t GetPlaneTimeZero(Int_t plane) const { return fPlaneTimeZero[plane-1];}
-
-  Double_t GetNSperChan() const { return fNSperChan;}
-
-  Double_t GetCenter(Int_t plane) const {
-    Int_t chamber = GetNChamber(plane)-1;
-    return
-      fXCenter[chamber]*sin(fAlphaAngle[plane-1]) +
-      fYCenter[chamber]*cos(fAlphaAngle[plane-1]);
-  }
   //  friend class THaScCalib;
 
   THcDriftChamber();  // for ROOT I/O
@@ -61,65 +49,58 @@ protected:
   // Calibration
 
   // Per-event data
+  Int_t fNhits;
 
-  // Potential Hall C parameters.  Mostly here for demonstration
-  Int_t fNPlanes;
-  char** fPlaneNames;
-  Int_t fNChambers;
-
-  Double_t fNSperChan;		/* TDC bin size */
-  Double_t fWireVelocity;
-
-  // Each of these will be dimensioned with the number of chambers
-  Double_t* fXCenter;
-  Double_t* fYCenter;
-
-  // Each of these will be dimensioned with the number of planes
-  // A THcDriftChamberPlane class object will need to access the value for
-  // its plane number.  Should we have a Get method for each or 
-  Int_t* fTdcWinMin;
-  Int_t* fTdcWinMax;
-  Int_t* fCentralTime;
-  Int_t* fNWires;		// Number of wires per plane
-  Int_t* fNChamber;
-  Int_t* fWireOrder;
-  Int_t* fDriftTimeSign;
-
-  Double_t* fZPos;
-  Double_t* fAlphaAngle;
-  Double_t* fBetaAngle;
-  Double_t* fGammaAngle;
-  Double_t* fPitch;
-  Double_t* fCentralWire;
-  Double_t* fPlaneTimeZero;
-
-  THcDriftChamberPlane** fPlanes; // List of plane objects
+  Int_t fNPlanes;		// Number of planes in the chamber
+
+  Int_t fChamberNum;
+
+  // HMS Specific
+  Int_t YPlaneInd; 		// Index of Yplane for this chamber
+  Int_t YPlanePInd; 		// Index of Yplanep for this chamber
+  Int_t YPlaneNum;		// Absolute plane number of Yplane
+  Int_t YPlanePNum;		// Absolute plane number of Yplanep
+
+  // Parameters 
+  Int_t fMinHits; 		// Minimum hits required to do something
+  Int_t fMaxHits; 		// Maximum required to do something
+  Int_t fMinCombos;             // Minimum # pairs in a space point
+  Int_t fRemove_Sppt_If_One_YPlane;
+
+  Double_t fXCenter;
+  Double_t fYCenter;
+  Double_t fSpacePointCriterion;
+  Double_t fSpacePointCriterion2;
+
+  THcDriftChamberPlane* fPlanes[20]; // List of plane objects
 
   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           ClearEvent();
   void           DeleteArrays();
   virtual Int_t  ReadDatabase( const TDatime& date );
   virtual Int_t  DefineVariables( EMode mode = kDefine );
 
   void Setup(const char* name, const char* description);
+  Int_t      FindEasySpacePoint(Int_t yplane_hitind, Int_t yplanep_hitind);
+  Int_t      FindHardSpacePoints(void);
+  Int_t      DestroyPoorSpacePoints(void);
+  Int_t      SpacePointMultiWire(void);
+  void       ChooseSingleHit(void);
+  void       SelectSpacePoints(void);
+
+  THcDCHit* fHits[10000];	/* All hits for this chamber */
+  // A simple structure until we figure out what we are doing.
+  struct SpacePoint {
+    Double_t x;
+    Double_t y;
+    Int_t nhits;
+    Int_t ncombos;
+    THcDCHit* hits[MAX_HITS_PER_POINT];
+  };
+  SpacePoint fSpacePoints[MAX_SPACE_POINTS];
+  Int_t fNSpacePoints;
+  Int_t fEasySpacePoint;	/* This event is an easy space point */
 
   ClassDef(THcDriftChamber,0)   // Drift Chamber class
 };
diff --git a/src/THcDriftChamberPlane.cxx b/src/THcDriftChamberPlane.cxx
index 816d27a650ea46865c1bd42f0655f5751de1ae1d..b23cfe21c160216f272ab7c3abd6cf807802dc2d 100644
--- a/src/THcDriftChamberPlane.cxx
+++ b/src/THcDriftChamberPlane.cxx
@@ -14,7 +14,7 @@
 #include "THcGlobals.h"
 #include "THcParmList.h"
 #include "THcHitList.h"
-#include "THcDriftChamber.h"
+#include "THcDC.h"
 #include "THcHodoscope.h"
 #include "TClass.h"
 
@@ -97,11 +97,11 @@ Int_t THcDriftChamberPlane::ReadDatabase( const TDatime& date )
   gHcParms->LoadParmValues((DBRequest*)&list,prefix);
 
   // Retrieve parameters we need from parent class
-  THcDriftChamber* fParent;
+  THcDC* fParent;
 
-  fParent = (THcDriftChamber*) GetParent();
+  fParent = (THcDC*) GetParent();
   // These are single variables here, but arrays in THcDriftChamber.
-  fNChamber = fParent->GetNChamber(fPlaneNum);
+  fChamberNum = fParent->GetNChamber(fPlaneNum);
   fNWires = fParent->GetNWires(fPlaneNum);
   fWireOrder = fParent->GetWireOrder(fPlaneNum);
   fPitch = fParent->GetPitch(fPlaneNum);
@@ -113,7 +113,34 @@ Int_t THcDriftChamberPlane::ReadDatabase( const TDatime& date )
 
   fNSperChan = fParent->GetNSperChan();
 
-  cout << fPlaneNum << " " << fNWires << endl;
+  // Calculate Geometry Constants
+  // Do we want to move all this to the Chamber of DC Package leve
+  // as that is where these things will be needed?
+  Double_t alpha = fParent->GetAlphaAngle(fPlaneNum);
+  Double_t beta = fParent->GetBetaAngle(fPlaneNum);
+  Double_t gamma = fParent->GetGammaAngle(fPlaneNum);
+  Double_t cosalpha = TMath::Cos(alpha);
+  Double_t sinalpha = TMath::Sin(alpha);
+  Double_t cosbeta = TMath::Cos(beta);
+  Double_t sinbeta = TMath::Sin(beta);
+  Double_t cosgamma = TMath::Cos(gamma);
+  Double_t singamma = TMath::Sin(gamma);
+  
+  Double_t hzchi = -cosalpha*sinbeta + sinalpha*cosbeta*singamma;
+  Double_t hzpsi =  sinalpha*sinbeta + cosalpha*cosbeta*singamma;
+  Double_t hxchi = -cosalpha*cosbeta - sinalpha*sinbeta*singamma;
+  Double_t hxpsi =  sinalpha*cosbeta - cosalpha*sinbeta*singamma;
+  Double_t hychi =  sinalpha*cosgamma;
+  Double_t hypsi =  cosalpha*cosgamma;
+
+  Double_t sumsqupsi = hzpsi*hzpsi+hxpsi*hxpsi+hypsi*hypsi;
+  Double_t sumsquchi = hzchi*hzchi+hxchi*hxchi+hychi*hychi;
+  Double_t sumcross = hzpsi*hzchi + hxpsi*hxchi + hypsi*hychi;
+  Double_t denom = sumsqupsi*sumsquchi-sumcross*sumcross;
+  fXsp = hychi/denom;
+  fYsp = -hxchi/denom;
+
+  cout << fPlaneNum << " " << fNWires << " " << fWireOrder << endl;
 
   fTTDConv = new THcDCLookupTTDConv(DriftMapFirstBin,fPitch/2,DriftMapBinSize,
 				    NumDriftMapBins,DriftMap);
@@ -242,7 +269,7 @@ Int_t THcDriftChamberPlane::ProcessHits(TClonesArray* rawhits, Int_t nexthit)
 	    - rawtdc*fNSperChan + fPlaneTimeZero;
 	  // How do we get this start time from the hodoscope to here
 	  // (or at least have it ready by coarse process)
-	  new( (*fHits)[nextHit++] ) THcDCHit(wire, rawtdc, time);
+	  new( (*fHits)[nextHit++] ) THcDCHit(wire, rawtdc, time, this);
 	}
 	wire_last = wireNum;
       }
diff --git a/src/THcDriftChamberPlane.h b/src/THcDriftChamberPlane.h
index 7307a4acf649f75679223878d27d2607747c3798..78faf37fefb33635e0c8ac1546c2ea9caf34abe2 100644
--- a/src/THcDriftChamberPlane.h
+++ b/src/THcDriftChamberPlane.h
@@ -48,6 +48,16 @@ class THcDriftChamberPlane : public THaSubDetector {
   { assert( i>=1 && i<=GetNWires() );
     return (THcDCWire*)fWires->UncheckedAt(i-1); }
 
+  Int_t         GetNHits() const { return fHits->GetLast()+1; }
+  TClonesArray* GetHits()  const { return fHits; }
+
+  Int_t        GetPlaneNum() const { return fPlaneNum; }
+  Int_t        GetChamberNum() const { return fChamberNum; }
+  void         SetPlaneIndex(Int_t index) { fPlaneIndex = index; }
+  Int_t        GetPlaneIndex() { return fPlaneIndex; }
+  Double_t     GetXsp() const { return fXsp; }
+  Double_t     GetYsp() const { return fYsp; }
+
  protected:
 
   TClonesArray* fParentHitList;
@@ -56,7 +66,8 @@ class THcDriftChamberPlane : public THaSubDetector {
   TClonesArray* fWires;
 
   Int_t fPlaneNum;
-  Int_t fNChamber;
+  Int_t fPlaneIndex;		/* Index of this plane within it's chamber */
+  Int_t fChamberNum;
   Int_t fNWires;
   Int_t fWireOrder;
   Int_t fTdcWinMin;
@@ -64,6 +75,8 @@ class THcDriftChamberPlane : public THaSubDetector {
   Double_t fPitch;
   Double_t fCentralWire;
   Double_t fPlaneTimeZero;
+  Double_t fXsp;
+  Double_t fYsp;
 
   Double_t fCenter;