////////////////////////////////////////////////////////////////////////
// Analysis Module for CandFitTrackCam
//
// For analysis and display of TrackFitting results
// Note the Pause() function which can be included or excluded in line 401
//
// marshall@hep.phy.cam.ac.uk
////////////////////////////////////////////////////////////////////////
#include "MessageService/MsgService.h"
#include "MinosObjectMap/MomNavigator.h"
#include "JobControl/JobCModuleRegistry.h"

#include "Validity/VldContext.h"

// Reconstruction includes
#include "RecoBase/CandStripHandle.h"
#include "RecoBase/CandSliceListHandle.h"
#include "RecoBase/CandSliceHandle.h"
#include "RecoBase/CandShowerListHandle.h"
#include "RecoBase/CandShowerHandle.h"
#include "RecoBase/CandTrackListHandle.h"
#include "RecoBase/CandTrackHandle.h"

#include "CandDigit/CandDeMuxDigitHandle.h"
#include "CandDigit/CandDeMuxDigit.h"

#include "CandFitTrackCam/CandFitTrackCamHandle.h"
#include "CandFitTrackCam/CandFitTrackCamListHandle.h"
#include "CandFitTrackCam/FitTrackCamAnalysisModule.h"

// For Truth info
#include "Record/SimSnarlRecord.h"
#include "Record/SimSnarlHeader.h"
#include "REROOT_Classes/REROOT_NeuKin.h"
#include "CandData/CandHeader.h"
#include "DataUtil/Truthifier.h"

// ROOT includes
#include "TH2F.h"
#include "TCanvas.h"
#include "TPad.h"
#include "TApplication.h"
#include "TSystem.h"
#include "TMarker.h"

// For pause function
#include <fcntl.h>
#include <unistd.h>

// for fabs()
#include <cmath>

using std::cout;
using std::endl;

JOBMODULE(FitTrackCamAnalysisModule, "FitTrackCamAnalysisModule", "Analyses track fit results");
CVSID("$Id: FitTrackCamAnalysisModule.cxx,v 1.12 2007/11/11 08:43:39 rhatcher Exp $");

////////////////////////////////////////////////////////////////////////
FitTrackCamAnalysisModule::FitTrackCamAnalysisModule()
{
  isMC=0;

  fListInSlc="CandSliceList";
  fListInShw="CandShowerList";
  fListInTrk="CandTrackSRList";
  fListInFitTrk="CandFitTrackCamList";

  fTrackCanvas = new TCanvas("fTrackCanvas","TrackView",800,500);
  fTrackCanvas->Draw();
  
  // Pads
  fUZPad   = new TPad("upad","U pad",0.010,0.505,0.495,0.990);
  fVZPad   = new TPad("vpad","V pad",0.010,0.010,0.495,0.495);
  fUZMCPad   = new TPad("uMCpad","U pad",0.505,0.505,0.990,0.990);
  fVZMCPad   = new TPad("vMCpad","V pad",0.505,0.010,0.990,0.495);

  fUZPad->SetFillColor(10);
  fVZPad->SetFillColor(10);
  fUZMCPad->SetFillColor(10);
  fVZMCPad->SetFillColor(10);

  fUZPad->SetLeftMargin(0.05);
  fUZPad->SetRightMargin(0.001);
  fUZPad->SetTopMargin(0.0001);
  fUZPad->SetBottomMargin(0.055);
  fVZPad->SetLeftMargin(0.05);
  fVZPad->SetRightMargin(0.001);
  fVZPad->SetTopMargin(0.0001);
  fVZPad->SetBottomMargin(0.055);

  fUZMCPad->SetLeftMargin(0.05);
  fUZMCPad->SetRightMargin(0.001);
  fUZMCPad->SetTopMargin(0.0001);
  fUZMCPad->SetBottomMargin(0.055);
  fVZMCPad->SetLeftMargin(0.05);
  fVZMCPad->SetRightMargin(0.001);
  fVZMCPad->SetTopMargin(0.0001);
  fVZMCPad->SetBottomMargin(0.055);

  fUZPad->Draw();
  fVZPad->Draw();
  fUZMCPad->Draw();
  fVZMCPad->Draw();

  fUZAxis=0;
  fVZAxis=0;
  fUZMCAxis=0;
  fVZMCAxis=0;


  // For writing results to file
  TDirectory* tmpd = 0;
  tmpd = gDirectory;  

  FTCFile = new TFile("FTCResults.root","recreate");
  FTCTree = new TTree("FTCTree","FTCTree");

  // Header info
  FTCTree->Branch("Run",&Run,"Run/I");
  FTCTree->Branch("Snarl",&Snarl,"Snarl/I");
  FTCTree->Branch("NumFittedTracks",&NumFittedTracks,"NumFittedTracks/I");
  FTCTree->Branch("Pass",&Pass,"Pass/I");

  // Momentum-related quantities
  FTCTree->Branch("RecoQP",&RecoQP,"RecoQP/D");
  FTCTree->Branch("TrueQP",&TrueQP,"TrueQP/D");
  FTCTree->Branch("QPVtxError",&QPVtxError,"QPVtxError/D");
  FTCTree->Branch("RecoMomCurve",&RecoMomCurve,"RecoMomCurve/D");
  FTCTree->Branch("RecoMomRange",&RecoMomRange,"RecoMomRange/D");
  FTCTree->Branch("TrueMom",&TrueMom,"TrueMom/D");
  FTCTree->Branch("RecoTime",&RecoTime,"RecoTime/D");

  // For checking tracking efficency
  FTCTree->Branch("FitTrackStrips",&FitTrackStrips,"FitTrackStrips/I");
  FTCTree->Branch("TrueMuonStrips",&TrueMuonStrips,"TrueMuonStrips/I");
  FTCTree->Branch("FitAndTruthAgree",&FitAndTruthAgree,"FitAndTruthAgree/I");
  FTCTree->Branch("FitTrackLength",&FitTrackLength,"FitTrackLength/I");
  FTCTree->Branch("TrueTrackLength",&TrueTrackLength,"TrueTrackLength/I");
  FTCTree->Branch("TotalStripsInSnarl",&TotalStripsInSnarl,"TotalStripsInSnarl/I");  
  FTCTree->Branch("FDFullyContained",&FDFullyContained,"FDFullyContained/I");
  FTCTree->Branch("NTrackStrip",&NTrackStrip,"NTrackStrip/I");
  FTCTree->Branch("NTrackDigit",&NTrackDigit,"NTrackDigit/I");

  // Track fit quality
  FTCTree->Branch("Chi2",&Chi2,"Chi2/D");
  FTCTree->Branch("NDOF",&NDOF,"NDOF/I");
  FTCTree->Branch("NIterate",&NIterate,"NIterate/I");
  FTCTree->Branch("NSwimFail",&NSwimFail,"NSwimFail/I");

  // Timing info
  FTCTree->Branch("TimeSlope",&TimeSlope,"TimeSlope/D");
  FTCTree->Branch("TimeOffset",&TimeOffset,"TimeOffset/D");
  FTCTree->Branch("VtxT",&VtxT,"VtxT/D");
  FTCTree->Branch("EndT",&EndT,"EndT/D");
  FTCTree->Branch("TimeFitChi2",&TimeFitChi2,"TimeFitChi2/D");
  FTCTree->Branch("NTimeFitDigit",&NTimeFitDigit,"NTimeFitDigit/D");
  FTCTree->Branch("TimeForwardFitRMS",&TimeForwardFitRMS,"TimeForwardFitRMS/D");
  FTCTree->Branch("TimeForwardFitNDOF",&TimeForwardFitNDOF,"TimeForwardFitNDOF/I");
  FTCTree->Branch("TimeBackwardFitRMS",&TimeBackwardFitRMS,"TimeBackwardFitRMS/D");
  FTCTree->Branch("TimeBackwardFitNDOF",&TimeBackwardFitNDOF,"TimeBackwardFitNDOF/I");
  
  // Vtx properties
  FTCTree->Branch("VtxU",&VtxU,"VtxU/D");
  FTCTree->Branch("VtxV",&VtxV,"VtxV/D");
  FTCTree->Branch("VtxZ",&VtxZ,"VtxZ/D");
  FTCTree->Branch("VtxPlane",&VtxPlane,"VtxPlane/I");

  FTCTree->Branch("VtxDirCosU",&VtxDirCosU,"VtxDirCosU/D");
  FTCTree->Branch("VtxDirCosV",&VtxDirCosV,"VtxDirCosV/D");
  FTCTree->Branch("VtxDirCosZ",&VtxDirCosZ,"VtxDirCosZ/D");

  FTCTree->Branch("VtxUError",&VtxUError,"VtxUError/D");
  FTCTree->Branch("VtxVError",&VtxVError,"VtxVError/D");
  FTCTree->Branch("VtxdUError",&VtxdUError,"VtxdUError/D");
  FTCTree->Branch("VtxdVError",&VtxdVError,"VtxdVError/D");


  // End properties
  FTCTree->Branch("EndU",&EndU,"EndU/D");
  FTCTree->Branch("EndV",&EndV,"EndV/D");
  FTCTree->Branch("EndZ",&EndZ,"EndZ/D");
  FTCTree->Branch("EndPlane",&EndPlane,"EndPlane/I");
  FTCTree->Branch("EndQP",&EndQP,"EndQP/D");

  FTCTree->Branch("EndDirCosU",&EndDirCosU,"EndDirCosU/D");
  FTCTree->Branch("EndDirCosV",&EndDirCosV,"EndDirCosV/D");
  FTCTree->Branch("EndDirCosZ",&EndDirCosZ,"EndDirCosZ/D");

  FTCTree->Branch("EndUError",&EndUError,"EndUError/D");
  FTCTree->Branch("EndVError",&EndVError,"EndVError/D");
  FTCTree->Branch("EnddUError",&EnddUError,"EnddUError/D");
  FTCTree->Branch("EnddVError",&EnddVError,"EnddVError/D");
  FTCTree->Branch("EndQOError",&EndQPError,"EndQPError/D");

  // Range and dS
  FTCTree->Branch("Range",&Range,"Range/D");
  FTCTree->Branch("dS",&dS,"dS/D");


  // Traces
  FTCTree->Branch("VtxTrace",&VtxTrace,"VtxTrace/D");
  FTCTree->Branch("VtxTraceZ",&VtxTraceZ,"VtxTraceZ/D");
  FTCTree->Branch("EndTrace",&EndTrace,"EndTrace/D");
  FTCTree->Branch("EndTraceZ",&EndTraceZ,"EndTraceZ/D");

  gDirectory = tmpd;
}
////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////
FitTrackCamAnalysisModule::~FitTrackCamAnalysisModule()
{
  if(fTrackCanvas) {delete fTrackCanvas;}

  if(fUZAxis) {delete fUZAxis;}
  if(fVZAxis) {delete fVZAxis;}
  if(fUZMCAxis) {delete fUZMCAxis;} 
  if(fVZMCAxis) {delete fVZMCAxis;} 
}
////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////
void FitTrackCamAnalysisModule::BeginJob()
{
}
////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////
void FitTrackCamAnalysisModule::EndJob()
{
  TDirectory* tmpd = 0;
  tmpd = gDirectory;  
  FTCFile->cd();
  FTCTree->Write();
  FTCFile->Close();
  gDirectory = tmpd;
}
////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////
JobCResult FitTrackCamAnalysisModule::Ana(const MomNavigator* mom)
{
  MSG("FitTrack", Msg::kDebug) << " FitTrackCamAnalysisModule::Ana(const MomNavigator* mom) " << endl;

  // Do we care about XTalk?
  CareAboutXTalk=true;
  debug=false;

  ////////////////////////////////////////////////////////
  // Make sure we have a 'clean' start
  if ( fUZAxis ) { delete fUZAxis; fUZAxis=0; }
  if ( fVZAxis ) { delete fVZAxis; fVZAxis=0; }
  if ( fUZMCAxis ) { delete fUZMCAxis; fUZMCAxis=0; }
  if ( fVZMCAxis ) { delete fVZMCAxis; fVZMCAxis=0; }
  
  fMaxZ = -1;
  fMinZ = 50;
  fMaxUorV = -20;
  fMinUorV = 20;

  fFitEndPlane = -1;
  fFitVtxPlane = 500;
  fTrueMaxPlane = -1;
  fTrueMinPlane = 500;

  Run=-999;
  Snarl=-999;
  NumFittedTracks=-999;
  Pass=-999;

  RecoQP=-999;
  TrueQP=-999;
  QPVtxError=-999;
  RecoMomCurve=-999;
  RecoMomRange=-999;
  TrueMom=-999;
  RecoTime=-999;

  FitTrackStrips=-999;
  TrueMuonStrips=-999;
  FitAndTruthAgree=-999;
  FitTrackLength=-999;
  TrueTrackLength=-999;
  TotalStripsInSnarl=-999;
  FDFullyContained=-999;
  NTrackStrip=-999;
  NTrackDigit=-999;

  Chi2=-999;
  NDOF=-999;
  NIterate=-999;
  NSwimFail=-999;

  TimeSlope=-999;
  TimeOffset=-999;
  VtxT=-999;
  EndT=-999;
  TimeFitChi2=-999;
  NTimeFitDigit=-999;
  TimeForwardFitRMS=-999;
  TimeForwardFitNDOF=-999;
  TimeBackwardFitRMS=-999;
  TimeBackwardFitNDOF=-999;

  VtxU=-999;
  VtxV=-999;	   
  VtxZ=-999;	   
  VtxPlane=-999; 
		   
  VtxDirCosU=-999;
  VtxDirCosV=-999;
  VtxDirCosZ=-999;
  
  VtxUError=-999;
  VtxVError=-999;
  VtxdUError=-999;
  VtxdVError=-999;
		   
  EndU=-999;	   
  EndV=-999;	   
  EndZ=-999;	   
  EndPlane=-999; 
  EndQP=-999;

  EndDirCosU=-999;
  EndDirCosV=-999;
  EndDirCosZ=-999;
		   
  EndUError=-999;
  EndVError=-999;
  EnddUError=-999;
  EnddVError=-999;
  EndQPError=-999;

  Range=-999;	   
  dS=-999;	   
  
  VtxTrace=-999; 
  VtxTraceZ=-999;
  EndTrace=-999; 
  EndTraceZ=-999;
  ////////////////////////////////////////////////////////


  // Needed by methods
  ////////////////////////////////////////////////////////
  candrec = dynamic_cast<CandRecord *> (mom->GetFragment("CandRecord", "PrimaryCandidateRecord"));
  
  if(!candrec)
    {
      MSG("FitTrack", Msg::kWarning) << " Failed to Find CandRecord " << endl;
      return JobCResult::kFailed;
    }

  // Header info
  CandHeader* candhead = (CandHeader*)(candrec->GetCandHeader());
  Run=candhead->GetRun();
  Snarl=candhead->GetSnarl();

  cout << "Snarl: " << Snarl << endl;

  VldContext *vldc = (VldContext*)(candrec->GetVldContext());  
  ////////////////////////////////////////////////////////


  // Run methods 
  ////////////////////////////////////////////////////////
  ConfigureAxes(vldc);
  SliceSection();
  ShowerSection();
  TrackSection();
  FittedTrackSection();


  // Truth section
  if(vldc->GetSimFlag()==SimFlag::kMC) {
    isMC=1;

    Truthifier* mytruth = new Truthifier(mom);

    //Get SimSnarlRecord
    SimSnarlRecord* simrec = dynamic_cast<SimSnarlRecord *>(mom->GetFragment("SimSnarlRecord"));
    if(simrec) {TruthSection(simrec);}
    
    TruthSliceSection(mytruth);
    EfficiencySection(mytruth);

    delete mytruth;
  }

  // Write ntuple
  TDirectory* tmpd = 0;
  tmpd = gDirectory;  
  FTCFile->cd();
  FTCTree->Fill();
  gDirectory = tmpd;

  Draw();
  //  Pause();
  CleanUp();
  ////////////////////////////////////////////////////////


  return JobCResult::kPassed; // kNoDecision, kFailed, etc.
}
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////



///////////////////////////////////////////////////////////////////////
void FitTrackCamAnalysisModule::ConfigureAxes(VldContext *vldc)  
{
  // Axes -  Determine for detector

  if (vldc->GetDetector()==Detector::kNear)
    {
      fUZAxis = new TH2F("UZAxis", "U view Near, Reco", 200, 0., 20., 80, -4., 4.);
      fVZAxis = new TH2F("VZAxis", "V view Near, Reco", 200, 0., 20., 80, -4., 4.);

      fUZMCAxis = new TH2F("UZMCAxis", "U view Near, Truth", 200, 0., 20., 80, -4., 4.);
      fVZMCAxis = new TH2F("VZMCAxis", "V view Near, Truth", 200, 0., 20., 80, -4., 4.);
    }
  else if (vldc->GetDetector()==Detector::kFar)
    {
      fUZAxis = new TH2F("UZAxis", "U view Far, Reco", 300, 0., 30., 100, -5., 5.);
      fVZAxis = new TH2F("VZAxis", "V view Far, Reco", 300, 0., 30., 100, -5., 5.);

      fUZMCAxis = new TH2F("UZMCAxis", "U view Far, Truth", 300, 0., 30., 100, -5., 5.);
      fVZMCAxis = new TH2F("VZMCAxis", "V view Far, Truth", 300, 0., 30., 100, -5., 5.);
    }
  else {cout << "Require detector to be near or far!!!" << endl;}

  // don't draw the Stats box
  fUZAxis->SetStats(kFALSE);
  fVZAxis->SetStats(kFALSE);
  fUZMCAxis->SetStats(kFALSE);
  fVZMCAxis->SetStats(kFALSE);

  // take away any association with a "directory" for these histograms
  fUZAxis->SetDirectory(0);
  fVZAxis->SetDirectory(0);
  fUZMCAxis->SetDirectory(0);
  fVZMCAxis->SetDirectory(0);

  // Draw empty canvas
  fUZPad->cd();
  fUZAxis->Draw();

  fVZPad->cd();
  fVZAxis->Draw();

  fUZMCPad->cd();
  fUZMCAxis->Draw();

  fVZMCPad->cd();
  fVZMCAxis->Draw();

  fTrackCanvas->cd();
}
///////////////////////////////////////////////////////////////////////



///////////////////////////////////////////////////////////////////////
void FitTrackCamAnalysisModule::SliceSection()
{
  vector<TMarker> fThisSliceUZ;
  vector<TMarker> fThisSliceVZ;
  CandSliceListHandle* slice_list = 0;

  // Get CandSliceListHandle
  slice_list = dynamic_cast<CandSliceListHandle*>
    (candrec->FindCandHandle("CandSliceListHandle",fListInSlc.Data()));

  if(!slice_list) {MSG("FitTrack", Msg::kWarning) << " Failed to Find " << fListInSlc.Data() << endl; }

  else {
    assert(slice_list);
    if(slice_list->GetNDaughters()<1) {MSG("FitTrack", Msg::kWarning) << "SliceList was empty... " << endl; }

    // loop over the slices
    TIter SlcItr = slice_list->GetDaughterIterator();
    while(CandSliceHandle* Slc = dynamic_cast<CandSliceHandle*>(SlcItr()))
      {
	
	TIter SlcStripItr = Slc->GetDaughterIterator();
	while(CandStripHandle* SlcStrip = dynamic_cast<CandStripHandle*>(SlcStripItr()))
	  {

	    TIter digitrSlcXTalk = SlcStrip->GetDaughterIterator();
	    while(CandDeMuxDigitHandle* SlcDigit = dynamic_cast<CandDeMuxDigitHandle*>(digitrSlcXTalk())) 
	      {
		// For U type planes
		if(int(SlcStrip->GetPlaneView())==2 && (SlcDigit->GetDeMuxDigitFlagWord()!=1 || CareAboutXTalk)) {
		  TMarker tmpmUSlc(SlcStrip->GetZPos(),  SlcStrip->GetTPos(), 20);	
		  tmpmUSlc.SetMarkerColor(3);
		  tmpmUSlc.SetMarkerSize(0.8);
		  fThisSliceUZ.push_back(tmpmUSlc);
		}
		
		// For V type planes
		else if(int(SlcStrip->GetPlaneView())==3 && (SlcDigit->GetDeMuxDigitFlagWord()!=1 || CareAboutXTalk)) {
		  TMarker tmpmVSlc(SlcStrip->GetZPos(),  SlcStrip->GetTPos(), 20);	
		  tmpmVSlc.SetMarkerColor(3);
		  tmpmVSlc.SetMarkerSize(0.8);
		  fThisSliceVZ.push_back(tmpmVSlc);
		}
		
		if(SlcStrip->GetZPos() > fMaxZ) fMaxZ=SlcStrip->GetZPos();
		if(SlcStrip->GetZPos() < fMinZ) fMinZ=SlcStrip->GetZPos();
		
		if(SlcStrip->GetTPos() > fMaxUorV) fMaxUorV=SlcStrip->GetTPos();
		if(SlcStrip->GetTPos() < fMinUorV) fMinUorV=SlcStrip->GetTPos();
	      }
	    digitrSlcXTalk.Reset();
	  }
	SlcStripItr.Reset();
	
	fUZSliceMarker.push_back(fThisSliceUZ);
	fVZSliceMarker.push_back(fThisSliceVZ);
      }
    SlcItr.Reset();
  }
}
///////////////////////////////////////////////////////////////////////



////////////////////////////////////////////////////////////////////////
void FitTrackCamAnalysisModule::ShowerSection()
{
  vector<TMarker> fThisShowerUZ;
  vector<TMarker> fThisShowerVZ;
  CandShowerListHandle* shower_list = 0;

  // Get CandShowerListHandle
  shower_list = dynamic_cast<CandShowerListHandle*>
    (candrec->FindCandHandle("CandShowerListHandle",fListInShw.Data()));

  if(!shower_list) {MSG("FitTrack", Msg::kWarning) << " Failed to Find " << fListInShw.Data() << endl; }

  else {
    assert(shower_list);
    if(shower_list->GetNDaughters()<1) {MSG("FitTrack", Msg::kWarning) << "ShowerList was empty... " << endl; }
    
    // loop over the showers
    TIter ShwItr = shower_list->GetDaughterIterator();
    while(CandShowerHandle* Shw = dynamic_cast<CandShowerHandle*>(ShwItr()))
      {
	
	TIter ShwStripItr = Shw->GetDaughterIterator();
	while(CandStripHandle* ShwStrip = dynamic_cast<CandStripHandle*>(ShwStripItr()))
	  {
	    
	    TIter digitrShwXTalk = ShwStrip->GetDaughterIterator();
	    while(CandDeMuxDigitHandle* ShwDigit = dynamic_cast<CandDeMuxDigitHandle*>(digitrShwXTalk())) 
	      {
		// For U type planes
		if(int(ShwStrip->GetPlaneView())==2 && (ShwDigit->GetDeMuxDigitFlagWord()!=1 || CareAboutXTalk)) {
		  TMarker tmpmUShw(ShwStrip->GetZPos(),  ShwStrip->GetTPos(), 24);	
		  tmpmUShw.SetMarkerColor(5);
		  fThisShowerUZ.push_back(tmpmUShw);
		}
		
		// For V type planes
		else if(int(ShwStrip->GetPlaneView())==3 && (ShwDigit->GetDeMuxDigitFlagWord()!=1 || CareAboutXTalk)) {
		  TMarker tmpmVShw(ShwStrip->GetZPos(),  ShwStrip->GetTPos(), 24);	
		  tmpmVShw.SetMarkerColor(5);
		  fThisShowerVZ.push_back(tmpmVShw);
		}
		
		if(ShwStrip->GetZPos() > fMaxZ) fMaxZ=ShwStrip->GetZPos();
		if(ShwStrip->GetZPos() < fMinZ) fMinZ=ShwStrip->GetZPos();
		
		if(ShwStrip->GetTPos() > fMaxUorV) fMaxUorV=ShwStrip->GetTPos();
		if(ShwStrip->GetTPos() < fMinUorV) fMinUorV=ShwStrip->GetTPos();
		
	      }
	    digitrShwXTalk.Reset();
	    
	  }
	ShwStripItr.Reset();
	
	fUZShowerMarker.push_back(fThisShowerUZ);
	fVZShowerMarker.push_back(fThisShowerVZ);
      }
    ShwItr.Reset();
  }
}
////////////////////////////////////////////////////////////////////////



////////////////////////////////////////////////////////////////////////
void FitTrackCamAnalysisModule::TrackSection()
{
  vector<TMarker> fThisTrackUZ;
  vector<TMarker> fThisTrackVZ;
  int numTrk=0;
  CandTrackListHandle* track_list = 0;

  // Get CandTrackListHandle
  track_list = dynamic_cast<CandTrackListHandle*>
    (candrec->FindCandHandle("CandTrackListHandle",fListInTrk.Data()));

  if(!track_list)    {MSG("Track", Msg::kWarning) << " Failed to Find " << fListInTrk.Data() << endl; }

  else {
    assert(track_list);
    if(track_list->GetNDaughters()<1) {MSG("Track", Msg::kWarning) << "Tracklist was empty... " << endl; }

    // loop over the simple tracks
    TIter TrkItr = track_list->GetDaughterIterator();
    while(CandTrackHandle* Trk = dynamic_cast<CandTrackHandle*>(TrkItr()))
      {
	numTrk++;


	TIter TrkStripItr = Trk->GetDaughterIterator();
	while(CandStripHandle* TrkStrip = dynamic_cast<CandStripHandle*>(TrkStripItr()))
	  {

	    TIter digitrTrkXTalk = TrkStrip->GetDaughterIterator();
	    while(CandDeMuxDigitHandle* TrkDigit = dynamic_cast<CandDeMuxDigitHandle*>(digitrTrkXTalk())) 
	      {
		// For U type planes
		if(int(TrkStrip->GetPlaneView())==2 && (TrkDigit->GetDeMuxDigitFlagWord()!=1 || CareAboutXTalk)) {
		  TMarker tmpmUTrk(TrkStrip->GetZPos(),  TrkStrip->GetTPos(), 24);	
		  tmpmUTrk.SetMarkerColor(4);
		  fThisTrackUZ.push_back(tmpmUTrk);
		}

		// For V type planes
		else if(int(TrkStrip->GetPlaneView())==3 && (TrkDigit->GetDeMuxDigitFlagWord()!=1 || CareAboutXTalk)) {
		  TMarker tmpmVTrk(TrkStrip->GetZPos(), TrkStrip->GetTPos(), 24);	
		  tmpmVTrk.SetMarkerColor(4);
		  fThisTrackVZ.push_back(tmpmVTrk);
		}
	
		if(TrkStrip->GetZPos() > fMaxZ) fMaxZ=TrkStrip->GetZPos();
		if(TrkStrip->GetZPos() < fMinZ) fMinZ=TrkStrip->GetZPos();
	  
		if(TrkStrip->GetTPos() > fMaxUorV) fMaxUorV=TrkStrip->GetTPos();
		if(TrkStrip->GetTPos() < fMinUorV) fMinUorV=TrkStrip->GetTPos();

	      }
	    digitrTrkXTalk.Reset();
	    
	  }
	TrkStripItr.Reset();

	fUZTrackMarker.push_back(fThisTrackUZ);
	fVZTrackMarker.push_back(fThisTrackVZ);
      }
    TrkItr.Reset();

    if(debug) {cout << "Number of simple tracks: " << numTrk << endl;}
  }
}
////////////////////////////////////////////////////////////////////////




////////////////////////////////////////////////////////////////////////
void FitTrackCamAnalysisModule::FittedTrackSection()
{
  vector<TMarker> fThisFitTrackUZ;
  vector<TMarker> fThisFitTrackVZ;
  int numFitTrk=0;
  CandFitTrackListHandle* fit_track_list = 0;

  // Get CandFitTrackListHandle
  fit_track_list = dynamic_cast<CandFitTrackListHandle*>
    (candrec->FindCandHandle("CandFitTrackListHandle",fListInFitTrk.Data()));

  if(!fit_track_list) {
    MSG("FitTrack", Msg::kWarning) << " Failed to Find " << fListInFitTrk.Data() << endl;
    NumFittedTracks=0;
    FitTrackLength=0;
  }

  else {
    assert(fit_track_list);
    if(fit_track_list->GetNDaughters()<1) {MSG("FitTrack", Msg::kWarning) << "FitTracklist was empty... " << endl; }

    // loop over the fittedtracks
    TIter FitTrkItr = fit_track_list->GetDaughterIterator();
    while(CandFitTrackCamHandle* FitTrk = dynamic_cast<CandFitTrackCamHandle*>(FitTrkItr()))
      {
	numFitTrk++;

	/////////////////////////////////
	// Fully contained?
	bool EndContained=false; bool VtxContained=false;

	if( fabs(FitTrk->GetEndU())<3.5 && fabs(FitTrk->GetEndV())<3.5 
	    && fabs( pow(0.5,0.5)*(FitTrk->GetEndU()-FitTrk->GetEndV()) )<3.5 
	    && fabs( pow(0.5,0.5)*(FitTrk->GetEndU()+FitTrk->GetEndV()) )<3.5
	    
	    && fabs( pow( pow(FitTrk->GetEndU(),2) + pow(FitTrk->GetEndV(),2),0.5) )>.4
	    
	    && (FitTrk->GetTermPlane())<480 && (FitTrk->GetTermPlane())>5

	    && ( (FitTrk->GetTermPlane())>254 || (FitTrk->GetTermPlane())<243 ) )
	  
	  {EndContained=true;}
	
	if( fabs(FitTrk->GetVtxU())<3.5 && fabs(FitTrk->GetVtxV())<3.5 
	    && fabs( pow(0.5,0.5)*(FitTrk->GetVtxU()-FitTrk->GetVtxV()) )<3.5 
	    && fabs( pow(0.5,0.5)*(FitTrk->GetVtxU()+FitTrk->GetVtxV()) )<3.5
	    
	    && fabs( pow( pow(FitTrk->GetVtxU(),2) + pow(FitTrk->GetVtxV(),2),0.5) )>.4
	    
	    && (FitTrk->GetVtxPlane())<480 && (FitTrk->GetVtxPlane())>5

	    && ( (FitTrk->GetVtxPlane())>254 || (FitTrk->GetVtxPlane())<243 ) )
	  
	  {VtxContained=true;}
	
	if(EndContained==true && VtxContained==true) {FDFullyContained=1;}
	else {FDFullyContained=0;}
	/////////////////////////////////


	TIter FitTrkStripItr = FitTrk->GetDaughterIterator();
	while(CandStripHandle* FitTrkStrip = dynamic_cast<CandStripHandle*>(FitTrkStripItr()))
	  {

	    TIter digitrFitTrkXTalk = FitTrkStrip->GetDaughterIterator();
	    while(CandDeMuxDigitHandle* FitTrkDigit = dynamic_cast<CandDeMuxDigitHandle*>(digitrFitTrkXTalk())) 
	      {
		// For U type planes
		if(int(FitTrkStrip->GetPlaneView())==2 && (FitTrkDigit->GetDeMuxDigitFlagWord()!=1 || CareAboutXTalk)) {
		  TMarker tmpmUFitTrk(FitTrkStrip->GetZPos(),  FitTrkStrip->GetTPos(), 23+numFitTrk);	
		  tmpmUFitTrk.SetMarkerColor(2);
		  fThisFitTrackUZ.push_back(tmpmUFitTrk);
		}

		// For V type planes
		else if(int(FitTrkStrip->GetPlaneView())==3 && (FitTrkDigit->GetDeMuxDigitFlagWord()!=1 || CareAboutXTalk)) {
		  TMarker tmpmVFitTrk(FitTrkStrip->GetZPos(), FitTrkStrip->GetTPos(), 23+numFitTrk);	
		  tmpmVFitTrk.SetMarkerColor(2);
		  fThisFitTrackVZ.push_back(tmpmVFitTrk);
		}
	
		if(FitTrkStrip->GetZPos() > fMaxZ) fMaxZ=FitTrkStrip->GetZPos();
		if(FitTrkStrip->GetZPos() < fMinZ) fMinZ=FitTrkStrip->GetZPos();
	  
		if(FitTrkStrip->GetTPos() > fMaxUorV) fMaxUorV=FitTrkStrip->GetTPos();
		if(FitTrkStrip->GetTPos() < fMinUorV) fMinUorV=FitTrkStrip->GetTPos();

		if(FitTrkStrip->GetPlane() > fFitEndPlane) fFitEndPlane=FitTrkStrip->GetPlane();
		if(FitTrkStrip->GetPlane() < fFitVtxPlane) fFitVtxPlane=FitTrkStrip->GetPlane();
	      }
	    digitrFitTrkXTalk.Reset();

	  }
	FitTrkStripItr.Reset();


	// Fill tree
	///////////////////////
	if(fit_track_list->GetNDaughters()==1) {
	  Pass=FitTrk->GetPass();

	  RecoMomCurve=FitTrk->GetMomentumCurve();
	  if(FitTrk->GetMomentumCurve()!=0) {RecoQP=FitTrk->GetEMCharge()/FitTrk->GetMomentumCurve();}
	  QPVtxError=FitTrk->GetVtxQPError();
	  RecoTime=FitTrk->GetCPUTime();

	  RecoMomRange=FitTrk->GetMomentumRange();

	  NTrackStrip=FitTrk->GetNTrackStrip();
	  NTrackDigit=FitTrk->GetNTrackDigit();

	  Chi2=FitTrk->GetChi2();
	  NDOF=FitTrk->GetNDOF();
	  NIterate=FitTrk->GetNIterate();
	  NSwimFail=FitTrk->GetNSwimFail();

	  TimeSlope=FitTrk->GetTimeSlope();
	  TimeOffset=FitTrk->GetTimeOffset();
	  VtxT=FitTrk->GetVtxT();
	  EndT=FitTrk->GetEndT();
	  TimeFitChi2=FitTrk->GetTimeFitChi2();
	  NTimeFitDigit=FitTrk->GetNTimeFitDigit();
	  TimeForwardFitRMS=FitTrk->GetTimeForwardFitRMS();
	  TimeForwardFitNDOF=FitTrk->GetTimeForwardFitNDOF();
	  TimeBackwardFitRMS=FitTrk->GetTimeBackwardFitRMS();
	  TimeBackwardFitNDOF=FitTrk->GetTimeBackwardFitNDOF();

	  VtxU=FitTrk->GetVtxU();
	  VtxV=FitTrk->GetVtxV();
	  VtxZ=FitTrk->GetVtxZ();
	  VtxPlane=FitTrk->GetVtxPlane();

	  VtxDirCosU=FitTrk->GetVtxDirCosU();
	  VtxDirCosV=FitTrk->GetVtxDirCosV();
	  VtxDirCosZ=FitTrk->GetVtxDirCosZ();

	  VtxUError=FitTrk->GetVtxUError();
	  VtxVError=FitTrk->GetVtxVError();
	  VtxdUError=FitTrk->GetVtxdUError();
	  VtxdVError=FitTrk->GetVtxdVError();

	  EndU=FitTrk->GetEndU();
	  EndV=FitTrk->GetEndV();
	  EndZ=FitTrk->GetEndZ();
	  EndPlane=FitTrk->GetTermPlane();
	  EndQP=FitTrk->GetEndQP();

	  EndDirCosU=FitTrk->GetEndDirCosU();
	  EndDirCosV=FitTrk->GetEndDirCosV();
	  EndDirCosZ=FitTrk->GetEndDirCosZ();

	  EndUError=FitTrk->GetEndUError();
	  EndVError=FitTrk->GetEndVError();
	  EnddUError=FitTrk->GetEnddUError();
	  EnddVError=FitTrk->GetEnddVError();
	  EndQPError=FitTrk->GetEndQPError();

	  Range=FitTrk->GetRange();
	  dS=FitTrk->GetdS();

	  VtxTrace=FitTrk->GetVtxTrace();
	  VtxTraceZ=FitTrk->GetVtxTraceZ();
	  EndTrace=FitTrk->GetEndTrace();
	  EndTraceZ=FitTrk->GetEndTraceZ();
	  
	  FitTrackLength=fFitEndPlane-fFitVtxPlane;
  
	  cout << "Cam Fitter charge * momentum result: " << FitTrk->GetEMCharge()*FitTrk->GetMomentumCurve() << endl;
	  cout << "Cam Fitter q/p vertex error: " << FitTrk->GetVtxQPError() << endl;
	  cout << "Cam Fitter CPU time: " << FitTrk->GetCPUTime() << endl;
	}
	else {
	  cout << "Multiple tracks!" << endl;
	  cout << "Cam Fitter charge * momentum result: " << FitTrk->GetEMCharge()*FitTrk->GetMomentumCurve() << endl;
	  cout << "Cam Fitter q/p vertex error: " << FitTrk->GetVtxQPError() << endl;
	  cout << "Cam Fitter CPU time: " << FitTrk->GetCPUTime() << endl;
	}
	//////////////////////

	fUZFitTrackMarker.push_back(fThisFitTrackUZ);
	fVZFitTrackMarker.push_back(fThisFitTrackVZ);
      }
    FitTrkItr.Reset();

    if(debug) {
      cout << "Number of fitted tracks: " << numFitTrk << endl;
      cout << "Fit track length: " << FitTrackLength << endl;}
    
    NumFittedTracks=numFitTrk;
  }
} 
////////////////////////////////////////////////////////////////////////



////////////////////////////////////////////////////////////////////////
void FitTrackCamAnalysisModule::TruthSection(SimSnarlRecord* simrec)
{   
  double fEmu=0;

  TObjArray arr(simrec->GetComponents());
  TIter iter(arr.MakeIterator());
  while(TObject* tob = (TObject*)(iter()))
    {
      if(tob->GetName()==TString("REROOT_NeuKin"))
	{
	  REROOT_NeuKin* nukin = dynamic_cast<REROOT_NeuKin*>(tob);
	  fEmu = nukin->P4Mu1()[3]; // Multiple muons?
	}   
    }
    
  cout << "--- True muon momentum * charge: " << fEmu << endl;


  // Get CandFitTrackListHandle
  CandFitTrackListHandle* fit_track_list = dynamic_cast<CandFitTrackListHandle*>
    (candrec->FindCandHandle("CandFitTrackListHandle",fListInFitTrk.Data()));

    
  // Fill tree
  ////////////////////
  if(fit_track_list) {
    if(fit_track_list->GetNDaughters()==1) {
      if(fEmu!=0.) {TrueQP=1./fEmu;}
      else{TrueQP=-999;}
      TrueMom=fabs(fEmu);
    }
    else {TrueQP=-999; TrueMom=-999;}
  }
  else {TrueQP=-999; TrueMom=-999;}
  //////////////////
  

  // Display
  //////////////////
  if(fit_track_list) {
    if(fEmu!=0. && fit_track_list->GetNDaughters()==1) {
      cout << "--- (Reco - Truth) / Truth: " << (RecoMomCurve-TrueMom)/ TrueMom << endl;
    }
  } 
  //////////////////

}
////////////////////////////////////////////////////////////////////////



////////////////////////////////////////////////////////////////////////
void FitTrackCamAnalysisModule::TruthSliceSection(Truthifier* mytruth)
{
  int numTrueMuonDigits=0;
  int numTrueMuonStrips=0;

  int numSliceStrips=0;

  vector<TMarker> fThisSliceUZTruth;
  vector<TMarker> fThisSliceVZTruth;

  vector<TMarker> fThisTrackUZTruth;
  vector<TMarker> fThisTrackVZTruth;

  // Get CandSliceListHandle
  CandSliceListHandle* slice_list = dynamic_cast<CandSliceListHandle*>
    (candrec->FindCandHandle("CandSliceListHandle",fListInSlc.Data()));

  if(!slice_list)    {MSG("FitTrack", Msg::kWarning) << " Failed to Find " << fListInSlc.Data() << endl;}

  else {
    assert(slice_list);
    if(slice_list->GetNDaughters()<1) {MSG("FitTrack", Msg::kWarning) << "SliceList was empty... " << endl; }     
      
    TIter SlcItrTruth = slice_list->GetDaughterIterator();
    while(CandSliceHandle* SlcTruth = dynamic_cast<CandSliceHandle*>(SlcItrTruth()))
      {
	
	TIter SlcStripItrTruth = SlcTruth->GetDaughterIterator();
	while(CandStripHandle* SlcStripTruth = dynamic_cast<CandStripHandle*>(SlcStripItrTruth()))
	  {
	    numSliceStrips++;

	    TIter digitrTruth = SlcStripTruth->GetDaughterIterator();
	    while(CandDeMuxDigitHandle* SlcDigitTruth = dynamic_cast<CandDeMuxDigitHandle*>(digitrTruth())) 
	      {	
		// For U type planes
		if(int(SlcStripTruth->GetPlaneView())==2 && (SlcDigitTruth->GetDeMuxDigitFlagWord()!=1 || CareAboutXTalk)) {
		  TMarker tmpmUSlcTruth(SlcStripTruth->GetZPos(),  SlcStripTruth->GetTPos(), 20);	
		  tmpmUSlcTruth.SetMarkerColor(3);
		  tmpmUSlcTruth.SetMarkerSize(0.8);
		  fThisSliceUZTruth.push_back(tmpmUSlcTruth);
		}
		  
		// For V type planes
		else if(int(SlcStripTruth->GetPlaneView())==3 && (SlcDigitTruth->GetDeMuxDigitFlagWord()!=1 || CareAboutXTalk)) {
		  TMarker tmpmVSlcTruth(SlcStripTruth->GetZPos(),  SlcStripTruth->GetTPos(), 20);	
		  tmpmVSlcTruth.SetMarkerColor(3);
		  tmpmVSlcTruth.SetMarkerSize(0.8);
		  fThisSliceVZTruth.push_back(tmpmVSlcTruth);
		}
		  
		  
		// Highlight true track and true showers, etc.
		if ( (mytruth->IsDigitFromParticle(13,*SlcDigitTruth)
		      || mytruth->IsDigitFromParticle(-13,*SlcDigitTruth))
		     
		     && mytruth->DigitIsOnlyCrosstalk(SlcDigitTruth)==0 )
		  {
		    // count number of true muon hit strips
		    numTrueMuonDigits++;
		    
		    // For U type planes
		    if(int(SlcStripTruth->GetPlaneView())==2) {
		      TMarker tmpmUTrkTruth(SlcStripTruth->GetZPos(),  SlcStripTruth->GetTPos(), 30);	
		      tmpmUTrkTruth.SetMarkerColor(2);
		      fThisTrackUZTruth.push_back(tmpmUTrkTruth);
		    }
		    
		    // For V type planes
		    else if(int(SlcStripTruth->GetPlaneView())==3) {
		      TMarker tmpmVTrkTruth(SlcStripTruth->GetZPos(),  SlcStripTruth->GetTPos(), 30);	
		      tmpmVTrkTruth.SetMarkerColor(2);
		      fThisTrackVZTruth.push_back(tmpmVTrkTruth);
		    }	  
		    
		    if(SlcStripTruth->GetPlane() > fTrueMaxPlane) {fTrueMaxPlane=SlcStripTruth->GetPlane();}
		    if(SlcStripTruth->GetPlane() < fTrueMinPlane) {fTrueMinPlane=SlcStripTruth->GetPlane();}
		  }
	      }
	    digitrTruth.Reset();

	    if(numTrueMuonDigits>0) {numTrueMuonStrips++;}
	    numTrueMuonDigits=0; // Reset counter
	    
	  }
	SlcStripItrTruth.Reset();
	
	if(debug) {
	  cout << "Total no. of hit strips: " << numSliceStrips << endl;
	  cout << "No. of true muon hit strips: " << numTrueMuonStrips << endl;}
	

	// Fill Tree - even if multiple tracks
	////////////////////
	TotalStripsInSnarl=numSliceStrips;
	TrueMuonStrips=numTrueMuonStrips;
	if(TrueMuonStrips!=0) {TrueTrackLength=fTrueMaxPlane-fTrueMinPlane;}
	else {TrueTrackLength=0;}
	////////////////////

	if(debug) {cout << "True track length: " << TrueTrackLength << endl;}


	fUZSliceMarkerTruth.push_back(fThisSliceUZTruth);
	fVZSliceMarkerTruth.push_back(fThisSliceVZTruth);

	fUZTrackMarkerTruth.push_back(fThisTrackUZTruth);
	fVZTrackMarkerTruth.push_back(fThisTrackVZTruth);
      }
  }
}
////////////////////////////////////////////////////////////////////////


 
////////////////////////////////////////////////////////////////////////
void FitTrackCamAnalysisModule::EfficiencySection(Truthifier* mytruth)
{
  int numFitTrkStrips=0;
  int numTrueMuonDigits=0;
  int numFitTrkTruthAgree=0;
    
  // Get CandFitTrackListHandle
  CandFitTrackListHandle* fit_track_list = dynamic_cast<CandFitTrackListHandle*>(candrec->FindCandHandle("CandFitTrackListHandle",
													 fListInFitTrk.Data()));
  if(!fit_track_list) {
    MSG("FitTrack", Msg::kWarning) << " Failed to Find " << fListInFitTrk.Data() << endl;
    FitTrackStrips=0;
    FitAndTruthAgree=0;
  }
  
  else {
    assert(fit_track_list);
    if(fit_track_list->GetNDaughters()<1) {MSG("FitTrack", Msg::kWarning) << "FitTracklist was empty... " << endl; }
      
    // loop over the fittedtracks
    TIter FitTrkItr = fit_track_list->GetDaughterIterator();
    while(CandFitTrackHandle* FitTrk = dynamic_cast<CandFitTrackHandle*>(FitTrkItr()))
      {

	TIter FitTrkStripItr = FitTrk->GetDaughterIterator();
	while(CandStripHandle* FitTrkStrip = dynamic_cast<CandStripHandle*>(FitTrkStripItr()))
	  {
	    numFitTrkStrips++;
	      
	    TIter digitrFitTrkXTalk = FitTrkStrip->GetDaughterIterator();
	    while(CandDeMuxDigitHandle* FitTrkDigit = dynamic_cast<CandDeMuxDigitHandle*>(digitrFitTrkXTalk())) 
	      {
		if ( ( mytruth->IsDigitFromParticle(13,*FitTrkDigit)
		       || mytruth->IsDigitFromParticle(-13,*FitTrkDigit) )
		       
		     && mytruth->DigitIsOnlyCrosstalk(FitTrkDigit)==0 )
		  {
		    // count number of true muon hit strips
		    numTrueMuonDigits++;
		  }
	      }
	    digitrFitTrkXTalk.Reset();
	      
	    if(numTrueMuonDigits>0) {numFitTrkTruthAgree++;}
	    numTrueMuonDigits=0;
	      
	  }
	FitTrkStripItr.Reset();
	  
	if(debug) {
	  cout << "No. of fit track hit strips: " << numFitTrkStrips << endl;
	  cout << "No. of fit track hits that agree with true muon hits: " << numFitTrkTruthAgree << endl;}


	//Fill tree
	///////////////////////////////
	if(fit_track_list->GetNDaughters()==1) {
	  FitTrackStrips=numFitTrkStrips;
	  FitAndTruthAgree=numFitTrkTruthAgree;
	}
	else {
	  FitTrackStrips=-999;
	  FitAndTruthAgree=-999;
	}
	///////////////////////////////

      }
    FitTrkItr.Reset();
  }
}
////////////////////////////////////////////////////////////////////////



////////////////////////////////////////////////////////////////////////
void FitTrackCamAnalysisModule::Draw()
{
  // Plot slices
  ///////////////////////////////////
  if(fUZSliceMarker.size() > 0) {
    fUZPad->cd();
    fUZAxis->GetXaxis()->SetRangeUser(fMinZ-0.1, fMaxZ+0.1);
    fUZAxis->GetYaxis()->SetRangeUser(fMinUorV-0.4, fMaxUorV+0.4);
    for(unsigned int j=0; j<fUZSliceMarker.size(); ++j) {
      if (fUZSliceMarker[j].size() > 0) {
	for(unsigned int i=0; i<fUZSliceMarker[j].size(); ++i) {  
	  fUZSliceMarker[j][i].Draw();
	}
      }
    }  
  }

  if(fVZSliceMarker.size() > 0) {
    fVZPad->cd();
    fVZAxis->GetXaxis()->SetRangeUser(fMinZ-0.1, fMaxZ+0.1);
    fVZAxis->GetYaxis()->SetRangeUser(fMinUorV-0.4, fMaxUorV+0.4);
    for(unsigned int j=0; j<fVZSliceMarker.size(); ++j) {
      if (fVZSliceMarker[j].size() > 0) {
	for(unsigned int i=0; i<fVZSliceMarker[j].size(); ++i) {
	  fVZSliceMarker[j][i].Draw();
	}
      }
    }
  }
  ///////////////////////////////////


  // Plot showers
  ///////////////////////////////////
  if (fUZShowerMarker.size() > 0) {  // Check to see if there are showers
    fUZPad->cd();
    fUZAxis->GetXaxis()->SetRangeUser(fMinZ-0.1, fMaxZ+0.1);
    fUZAxis->GetYaxis()->SetRangeUser(fMinUorV-0.4, fMaxUorV+0.4);
    for(unsigned int j=0; j<fUZShowerMarker.size(); ++j) {
      if (fUZShowerMarker[j].size() > 0) {
	for(unsigned int i=0; i<fUZShowerMarker[j].size(); ++i) {  
	  fUZShowerMarker[j][i].Draw();
	}
      }
    }  
  }

  if (fVZShowerMarker.size() > 0) { 
    fVZPad->cd();
    fVZAxis->GetXaxis()->SetRangeUser(fMinZ-0.1, fMaxZ+0.1);
    fVZAxis->GetYaxis()->SetRangeUser(fMinUorV-0.4, fMaxUorV+0.4);
    for(unsigned int j=0; j<fVZShowerMarker.size(); ++j) {
      if (fVZShowerMarker[j].size() > 0) {
	for(unsigned int i=0; i<fVZShowerMarker[j].size(); ++i) {
	  fVZShowerMarker[j][i].Draw();
	}
      }
    }
  }
  /////////////////////////////////// 


  // Plot simple tracks
  ///////////////////////////////////
  if (fUZTrackMarker.size() > 0) {  // Check to see if there are tracks
    fUZPad->cd();
    fUZAxis->GetXaxis()->SetRangeUser(fMinZ-0.1, fMaxZ+0.1);
    fUZAxis->GetYaxis()->SetRangeUser(fMinUorV-0.4, fMaxUorV+0.4);
    for(unsigned int j=0; j<fUZTrackMarker.size(); ++j) {
      if (fUZTrackMarker[j].size() > 0) {
	for(unsigned int i=0; i<fUZTrackMarker[j].size(); ++i) {  
	  fUZTrackMarker[j][i].Draw();
	}
      }
    }
  }
 
  if (fVZTrackMarker.size() > 0) {  
    fVZPad->cd();
    fVZAxis->GetXaxis()->SetRangeUser(fMinZ-0.1, fMaxZ+0.1);
    fVZAxis->GetYaxis()->SetRangeUser(fMinUorV-0.4, fMaxUorV+0.4);
    for(unsigned int j=0; j<fVZTrackMarker.size(); ++j) {
      if (fVZTrackMarker[j].size() > 0) {
	for(unsigned int i=0; i<fVZTrackMarker[j].size(); ++i) {  
	  fVZTrackMarker[j][i].Draw();
	}
      }
    }
  }
  /////////////////////////////////// 



  // Plot fitted tracks
  ///////////////////////////////////
  if (fUZFitTrackMarker.size() > 0) {  // Check to see if there are fitted tracks
    fUZPad->cd();
    fUZAxis->GetXaxis()->SetRangeUser(fMinZ-0.1, fMaxZ+0.1);
    fUZAxis->GetYaxis()->SetRangeUser(fMinUorV-0.4, fMaxUorV+0.4);
    for(unsigned int j=0; j<fUZFitTrackMarker.size(); ++j) {
      if (fUZFitTrackMarker[j].size() > 0) {
	for(unsigned int i=0; i<fUZFitTrackMarker[j].size(); ++i) {  
	  fUZFitTrackMarker[j][i].Draw();
	}
      }
    }
  }

  if (fVZFitTrackMarker.size() > 0) {
    fVZPad->cd();
    fVZAxis->GetXaxis()->SetRangeUser(fMinZ-0.1, fMaxZ+0.1);
    fVZAxis->GetYaxis()->SetRangeUser(fMinUorV-0.4, fMaxUorV+0.4);
    for(unsigned int j=0; j<fVZFitTrackMarker.size(); ++j) {
      if (fVZFitTrackMarker[j].size() > 0) {
	for(unsigned int i=0; i<fVZFitTrackMarker[j].size(); ++i) {  
	  fVZFitTrackMarker[j][i].Draw();
	}
      }
    }
  }
  ///////////////////////////////////


  // Truth section plot
  ///////////////////////////////////
  if (isMC==1) {
    
    // All slice
    if(fUZSliceMarkerTruth.size() > 0) {
      fUZMCPad->cd();
      fUZMCAxis->GetXaxis()->SetRangeUser(fMinZ-0.1, fMaxZ+0.1);
      fUZMCAxis->GetYaxis()->SetRangeUser(fMinUorV-0.4, fMaxUorV+0.4);
      for(unsigned int j=0; j<fUZSliceMarkerTruth.size(); ++j) {
	if (fUZSliceMarkerTruth[j].size() > 0) {
	  for(unsigned int i=0; i<fUZSliceMarkerTruth[j].size(); ++i) {  
	    fUZSliceMarkerTruth[j][i].Draw();
	  }
	}
      }  
    }
    
    if(fVZSliceMarkerTruth.size() > 0) {
      fVZMCPad->cd();
      fVZMCAxis->GetXaxis()->SetRangeUser(fMinZ-0.1, fMaxZ+0.1);
      fVZMCAxis->GetYaxis()->SetRangeUser(fMinUorV-0.4, fMaxUorV+0.4);
      for(unsigned int j=0; j<fVZSliceMarkerTruth.size(); ++j) {
	if (fVZSliceMarkerTruth[j].size() > 0) {
	  for(unsigned int i=0; i<fVZSliceMarkerTruth[j].size(); ++i) {
	    fVZSliceMarkerTruth[j][i].Draw();
	  }
	}
      }
    }

    // True tracks... muon hits, etc
    if(fUZTrackMarkerTruth.size() > 0) {
      fUZMCPad->cd();
      fUZMCAxis->GetXaxis()->SetRangeUser(fMinZ-0.1, fMaxZ+0.1);
      fUZMCAxis->GetYaxis()->SetRangeUser(fMinUorV-0.4, fMaxUorV+0.4);
      for(unsigned int j=0; j<fUZTrackMarkerTruth.size(); ++j) {
	if (fUZTrackMarkerTruth[j].size() > 0) {
	  for(unsigned int i=0; i<fUZTrackMarkerTruth[j].size(); ++i) {  
	    fUZTrackMarkerTruth[j][i].Draw();
	  }
	}
      }  
    }
    
    if(fVZTrackMarkerTruth.size() > 0) {
      fVZMCPad->cd();
      fVZMCAxis->GetXaxis()->SetRangeUser(fMinZ-0.1, fMaxZ+0.1);
      fVZMCAxis->GetYaxis()->SetRangeUser(fMinUorV-0.4, fMaxUorV+0.4);
      for(unsigned int j=0; j<fVZTrackMarkerTruth.size(); ++j) {
	if (fVZTrackMarkerTruth[j].size() > 0) {
	  for(unsigned int i=0; i<fVZTrackMarkerTruth[j].size(); ++i) {
	    fVZTrackMarkerTruth[j][i].Draw();
	  }
	}
      }
    }
    
  }
  ///////////////////////////////////

  fTrackCanvas->cd();
  fTrackCanvas->Update();
}
////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////
void FitTrackCamAnalysisModule::Pause()
{
  cout << "Press return to continue" << endl;

  int key = 0;
  while(1){
    gSystem->ProcessEvents();
    fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);
    key = getchar();
    if(key=='\n') break;
    usleep(1000);
  }
}
////////////////////////////////////////////////////////////////////////



////////////////////////////////////////////////////////////////////////
void FitTrackCamAnalysisModule::CleanUp()
{
  fUZSliceMarker.clear();
  fVZSliceMarker.clear();

  fUZShowerMarker.clear();
  fVZShowerMarker.clear();

  fUZTrackMarker.clear();
  fVZTrackMarker.clear();

  fUZFitTrackMarker.clear();
  fVZFitTrackMarker.clear();

  fUZSliceMarkerTruth.clear();
  fVZSliceMarkerTruth.clear();

  fUZTrackMarkerTruth.clear();
  fVZTrackMarkerTruth.clear();
}
////////////////////////////////////////////////////////////////////////



////////////////////////////////////////////////////////////////////////
const Registry& FitTrackCamAnalysisModule::DefaultConfig() const
{
  //======================================================================
  // Supply the default configuration for the module
  //======================================================================
  static Registry r; // Default configuration for module

  // Set name of config
  std::string name = this->GetName();
  name += ".config.default";
  r.SetName(name.c_str());

  // Set values in configuration
  r.UnLockValues();
  r.Set("NameSlcListIn","CandSliceList");
  r.Set("NameShwListIn","CandShowerList");
  r.Set("NameTrkListIn","CandTrackSRList");
  r.Set("NameFitTrkListIn","CandFitTrackCamList");
  r.Set("NameFileOut","FitTrackCamAna.root");
  r.LockValues();

  return r;
}
////////////////////////////////////////////////////////////////////////



////////////////////////////////////////////////////////////////////////
void FitTrackCamAnalysisModule::Config(const Registry& r)
{
  //======================================================================
  // Configure the module given the Registry r
  //======================================================================
  const char* tmps;
  if (r.Get("NameSlcListIn",tmps)) { fListInSlc = tmps; }
  if (r.Get("NameShwListIn",tmps)) { fListInShw = tmps; }
  if (r.Get("NameTrkListIn",tmps)) { fListInTrk = tmps; }
  if (r.Get("NameFitTrkListIn",tmps)) { fListInFitTrk = tmps; }
  if (r.Get("NameFileOut",tmps)) { fFileName = tmps; }
}
////////////////////////////////////////////////////////////////////////
