BRAT 2.4.5
Class index
Full class index
brahmlib
BRAHMS
ROOT page
// $Id: BrDigitizeTPC.cxx,v 1.5 2001/11/13 21:11:24 trulsml Exp $
// $Author: trulsml $
// $Date: 2001/11/13 21:11:24 $
//

//________________________________________________________________________
//
// The BRDigitize TPC is the digitization module for the
// pad TPC's. The module performs a slow digitization using the
// geant hit information. The output is in tables of the BrTPCsequence
// i.e. a structure that very closely resembles the output from the
// TPC front ends.
//
// The Detector geometry comes from two sources
// BrDetectorVolume which is set using the BrGeometryDbManager
// and from the BrDetectorParamsTPC
//
// The method has the standard Module entry points implemented
//
// Init()
// Event() 
// DefineHistograms() (called from Book()
//
// Note Init() must be called explicitely (Nov 2000). It has been removed from the
// constructor.
//
// December 1999
//  The conversion between intrincis (Geant coordinates) and Pad Time
//  etc are now done through a set of BrDetectorParamsTPC methods. This
//  hides all explicit references to geometry in this code, and makes it much
//  more aminable to introduction of dabatbase calls.
//
// January 2000
//  Modifications made to deal with dynamic allocation of adc value rather than fixed
//  size. A compile flag DYNAMIC is used to enable this feature.
//
//  All direct references to intrinsic to pad,bucket now removed. All is
//  converted through calls to BrDetectorParamsTPC methods.
//  Note that the drift now goes towards positive Y values (up), and that
//  the pads are counted from the postive X towards lower values.
//
//  August 2000
//  The non dynamic code is scheduled to be removed soon
// 

//
//	System includes
//
#include "math.h"
#include <stdlib.h>
#ifdef UNIX
#include <unistd.h>
#endif

#include <BrIostream.h>
//
//  Root includes
//

#ifndef ROOT_TDirectory
#include "TDirectory.h"
#endif

#include "TRandom.h"
#include "TH1.h"
#include "TROOT.h"
#include "TCanvas.h"
#include "TView.h"

//
//  BRAT includes
//
#include "BrDigitizeTPC.h"
#include "BrMath.h"
#include "BrGeometryDbManager.h"
#include "BrParameterDbManager.h"
#include "BrDetectorParamsTPC.h"
#include "BrDetectorVolume.h"
#include "BrEventNode.h"
#include "BrDigitizeTPC.h"
#include "BrDataTable.h"
#include "BrGeantHit.h"
#include "BrTpcSequence.h"
#include "BrUnits.h"
#include "TClonesArray.h"

//Stuff for Event Display
#include "BrDetectorTPC.h"

#define DYNAMIC

//________________________________________________________________________

ClassImp(BrDigitizeTPC);

//________________________________________________________________________
 BrDigitizeTPC::BrDigitizeTPC()
{
  // Default Constructor. Should only be used by ROOT internal. Use
  // BrDigitize(Title,name) instead.
  fParams_p       = 0;
  fVolumeParams_p = 0;
  fDetectorNode   = 0;
  fAdcVal         = 0;

  fUseGongTimeResp = kFALSE;  
  fUseHyperbolic = kFALSE;
  fTauScale = 0.5;  // Must be adjusted empirically!
  fTshift = 2.5;  // Probably OK
  fN0_pad_to_tot = 1.0; // default
  fAbsorp = 0.0;  // default
  fMinNbins = 2; // corresponds to original, hardcoded value

  SetState(kSetup);

}

//________________________________________________________________________
 BrDigitizeTPC::BrDigitizeTPC(const Char_t *Name, const Char_t *Title) 
  : BrModule(Name, Title)
{
	//  Constructor to call from user code.
	//
  fParams_p       = 0;
  fVolumeParams_p = 0;
  fDetectorNode   = 0;
  fAdcVal =0;
  
  fAdcCut = 4.0;
  fNoise  = 0.0;
#ifdef WIN32
  fDedxTon0 = (Float_t)(1.0 / (.045*0.001)/3.0);
#else
  fDedxTon0 = (Float_t)(1.0 / (.045*BrUnits::keV)/3.0);
#endif 

  fUseGongTimeResp = kFALSE;
  fUseHyperbolic = kFALSE;
  fTauScale = 0.5;  // Must be adjusted empirically!
  fTshift = 2.5;  // Probably OK
  fN0_pad_to_tot = 1.0; // default
  fAbsorp = 0.0;  // default
  
  fMinNbins = 2; // corresponds to original, hardcoded value

  SetState(kSetup);

}

//______________________________________________________________________________
 void BrDigitizeTPC::ListDetectorParameters(){
// List the current value of the digitization parameters on
// standard out. 
if( fParams_p != NULL)
	fParams_p->ListParameters();
else
cout << "No parameters set for this Digitisation module" << endl;
if(fVolumeParams_p)
  fVolumeParams_p ->ListParameters();
}

//______________________________________________________________________________
void 
 BrDigitizeTPC::ListEventStatistics() {
  BrModule::ListEventStatistics();
//  cout<<"NumGeantHits = "<<fNumGeantHits << endl;
}

//______________________________________________________________________________
 BrDigitizeTPC::~BrDigitizeTPC(){
 

  if(fDetectorNode) delete fDetectorNode;

  if(fAdcVal){
    for(int i=(fNpads-1);i>=0;i--)
      {
	delete [] fAdcVal[i];
      }
    if (DebugLevel() > 0)
      cout << "delete index Table" << endl;
    delete [] fAdcVal;
  }

  delete [] fDiffused_array;
  delete [] fShaped_array;
  delete [] fFinal_array;
  delete [] fShaper_lookup_array;

    
}

//______________________________________________________________________________
 void BrDigitizeTPC::Init() {
  // The init member function/method is used. Intended to be used for setting
  // up internals that cannot be done at the time of module construction or
  // after parameters has been modified.
  // Job-level initialisation
  SetState(kInit);

  // Get volume data with GeometryDbManager
  // Note the volume is not used anywhere except in the Draw.
  BrGeometryDbManager *gGeomDb = BrGeometryDbManager::Instance();
  fVolumeParams_p = (BrDetectorVolume*) 
    gGeomDb->GetDetectorVolume("BrDetectorVolume", GetName());
  
  BrParameterDbManager *gParamDb = BrParameterDbManager::Instance();
  fParams_p = (BrDetectorParamsTPC*) 
    gParamDb->GetDetectorParameters("BrDetectorParamsTPC",GetName());


  if(fAdcVal){
  for(int i=(fNpads-1);i>=0;i--)
    {
	delete [] fAdcVal[i];
    }
  if (DebugLevel() > 0)
    cout << "delete index Table" << endl;

  delete [] fAdcVal;
  }
  // Note the use of fNpads and fNbuckets as private data members of the class
  // The are only modifed though a call to Init() to ensure intregity of fAdcVal
  // 2D array.
  fNpads    = fParams_p->GetPadsprow();
  fNbuckets = fParams_p->GetNoBuckets(); 
  
  Float_t** val = new Float_t * [fNpads];
  for(int i=0;i<fNpads;i++){
    val[i] = new Float_t [fNbuckets];
  }
  fAdcVal = val;

  fDiffused_array = new Float_t [fNbuckets*10];
  fShaped_array = new Float_t [fNbuckets*10];
  fFinal_array = new Float_t [fNbuckets*10];
  fShaper_lookup_array = new Float_t [fNbuckets*10];


}

//_______________________________________________________________________________
 void BrDigitizeTPC::DefineHistograms()
{
  //
  // Book histograms (called from BrModule::Book)
  //

  // Define histograms. They are:
  // <fill in here>

  if (GetState() != kInit) {
    Stop("DefineHistograms", "Must be called after Init"); 
    return;  
  }

  TDirectory* saveDir = gDirectory; 
  TDirectory* histDir = gDirectory->mkdir(Form("%s_Digitize", GetName())); 
  histDir->cd();

  hNGeantHits = new TH1F(Form("hNGeantHits%s", GetName()), Form("Geant Hits per event%s", GetName()), 100, 0., 500.);
  hNSequences = new TH1F(Form("hNSequences%s", GetName()), Form("Sequences per event%s", GetName()), 500, 0., 5000.);
  hNTimebins = new TH1F(Form("hNTimebins%s", GetName()), Form("Timebins per sequence%s", GetName()), 25, 0., 25.);
  hAdcDist = new TH1F(Form("hAdcDist%s", GetName()), Form("ADC distribution%s", GetName()), 1000, 0.,1000.);
  hAdcSumDist = new TH1F(Form("hAdcSumDist%s", GetName()), Form("ADC sum distribution%s", GetName()), 1000, 0.,5000.);
  hN0Dist = new TH1F(Form("hN0Dist%s", GetName()), Form("N0 e- distribution%s", GetName()), 1000, 0.,1000.);
  hSigmaTDist = new TH1F(Form("hSigmaTDist%s", GetName()), Form("Transverse cluster width%s", GetName()), 50, 0.,5.);
  hSigmaLDist = new TH1F(Form("hSigmaLDist%s", GetName()), Form("Longitudinal cluster width%s", GetName()), 50, 0.,5.);
  hSigmaLTotDist = new TH1F(Form("hSigmaLTotDist%s", GetName()), Form("Longitudinal width of shaped clusters%s", GetName()), 50, 0.,5.);
  hSigmaTRes = new TH1F(Form("hSigmaTRes%s", GetName()), Form("Transverse residual%s", GetName()), 50, -2.,2.);
  hSigmaLRes = new TH1F(Form("hSigmaLRes%s", GetName()), Form("Longitudinal residual%s", GetName()), 50, -2.,2.);

  hPadCentroid = new TH1F(Form("hPadCentroid%s", GetName()), Form("Centroid of pad%s", GetName()), fNpads, 0.,(Float_t)fNpads);
  hSequenceCentroid = new TH1F(Form("hSequenceCentroid%s", GetName()), Form("Centroid of sequence%s", GetName()), 155, 0.,155);
  hSequenceCentroidDecimal = new TH1F(Form("hSequenceCentroidDecimal%s", GetName()), Form("Centroid of sequence - integer%s", GetName()), 200, 0.,1.0);
  hYmiss = new TH1F(Form("hYmiss%s", GetName()), Form("Distance between hit and sequence centroid", GetName()), 200,-3.0,3.0);
  hXDistToHit = new TH1F(Form("hXDistToHit%s", GetName()), Form("Distance hit - pad centroid", GetName()), 200,-3.0,3.0);
  hYDistToHit = new TH1F(Form("hYDistToHit%s", GetName()), Form("Distance hit - time centroid", GetName()), 200,-3.0,3.0);
  hPadShape = new TProfile(Form("hPadShape%s", GetName()), Form("Shape of cluster in pad%s", GetName()), 20, -10.,10.,0.0,1.0);
  hShapeResp = new TProfile(Form("hShapeResp%s", GetName()), Form("Shaper response%s", GetName()), 100, 0., 100.,0.0,1.0);
  hTimeCluster2D = new TH2F(Form("hTimeCluster2D%s", GetName()), Form("Time shape of orig cluster%s", GetName()), 30, -15., 15.,100,0.0,1.0);
  hTimeShape2D = new TH2F(Form("hTimeShape2D%s", GetName()), Form("Time shape of folded cluster%s", GetName()), 30, -15., 15.,100,0.0,1.0);
  hPadShape2D = new TH2F(Form("hPadShape2D%s", GetName()), Form("Shape of cluster in pad%s", GetName()), 20, -10.,10.,100,0.0,1.0);
  hSequenceShape = new TProfile(Form("hSequenceShape%s", GetName()), Form("Shape of sequence%s", GetName()), 30, -15,15.,0.0,1.0);
  hSequenceShapeY2D = new TH2F(Form("hSequenceShapeY2D%s", GetName()), Form("Shape of sequence vs Y%s",GetName()),20,-10,10,30,-15,15);
  hSequenceShapeYsl2D = new TH2F(Form("hSequenceShapeYsl2D%s", GetName()), Form("Shape of sequence vs Ysl%s",GetName()),20,-1.0,1.0,50,-25,25);

  hSigmaTVsY = new TProfile(Form("hSigmaTVsY%s", GetName()), Form("Pad width vs drift length%s", GetName()),20,-10,10,0.0,5.0);
  hSigmaTVsXsl = new TProfile(Form("hSigmaTVsXsl%s", GetName()), Form("Pad width vs X slope%s", GetName()),20,-1.0,1.0,0.0,10.0);

  hSigmaLVsY = new TProfile(Form("hSigmaLVsY%s", GetName()), Form("Time width vs drift length%s", GetName()),20,-10,10,0.0,5.0);
  hSigmaLTotVsY = new TProfile(Form("hSigmaLTotVsY%s", GetName()), Form("Tot. time width vs drift length%s", GetName()),20,-10,10,0.0,5.0);
  hSigmaLTotVsY2D = new TH2F(Form("hSigmaLTotVsY2D%s", GetName()), Form("Tot. time width vs drift length%s", GetName()),20,-10,10,50,0.0,5.0);
  hSigmaLTotVsYsl = new TProfile(Form("hSigmaLTotVsYsl%s", GetName()), Form("Tot time width vs Y slope%s", GetName()),20,-1.0,1.0,0.0,10.0);
  hSigmaLTotVsYsl2D = new TH2F(Form("hSigmaLTotVsYsl2D%s", GetName()), Form("Tot. time width vs Y slope%s", GetName()),20,-1.0,1.0,50,0.0,10.0);
  hSigmaTResVsY = new TProfile(Form("hSigmaTResVsY%s", GetName()), Form("Trans resid vs drift length%s", GetName()),20,-10,10,0.0,2.0);
  hSigmaLResVsY = new TProfile(Form("hSigmaLResVsY%s", GetName()), Form("Long resid vs drift length%s", GetName()),20,-10,10,0.0,2.0);
  hSigmaTResVsXsl = new TProfile(Form("hSigmaTResVsXsl%s", GetName()), Form("Trans resid vs Xslope%s", GetName()),20,-0.5,0.5,0.0,2.0);
  hSigmaLResVsYsl = new TProfile(Form("hSigmaLResVsYsl%s", GetName()), Form("Long resid vs Yslope%s", GetName()),20,-0.5,0.5,0.0,2.0);
  hSigmaTResVsN0 = new TProfile(Form("hSigmaTResVsN0%s", GetName()), Form("Trans resid vs charge%s", GetName()),50,0,250,0.0,2.0);
  hSigmaLResVsN0 = new TProfile(Form("hSigmaLResVsN0%s", GetName()), Form("Long resid vs charge%s", GetName()),50,0,250,0.0,2.0);
  gDirectory = saveDir;

}

//______________________________________________________________________________
 void BrDigitizeTPC::Event(BrEventNode* InputTable, BrEventNode* OutputTable)
{
  // Event method to be called once per event. 
  // This performes the actual slow simulation of the hits on the TPC.
  //
  //
  //
  //
  // The code has been changed (Feb 99) to be able to create sequences of
  // TPC data. The algorithm does not complete mimic the one presently
  // implemented in the
  // readout board. The conditions to create an adc cluster is
  // - #consequtive bins with AdcValue above fAdcCut must be two
  // - once a single bins goes below the cut the sequence is generated.
  //   This later condition is strciter than the readoutboard which requires
  //   2 (3?) bins below the cut.
  //

 SetState(kEvent);


 //  const Bool_t hyperbolic = kFALSE;
#ifdef WIN32
  const double pi = 3.1415926;
  const double twopi = 2.0*pi;
#else
  const double pi = BrUnits::pi ;
  const double twopi = BrUnits::twopi;
#endif
  const Float_t  sqtwopi = (Float_t)BrMath::Sqrt(twopi);
  const Float_t  sqtwo = Float_t(sqrt(2.));
    
  Float_t a,b,z,ax,ay,n0,xlo,xhi,dxl,dxt,xc,yc;
  Float_t time_bucket, Anode_Gap, sigma_0, sigma_prf,path_length;
  Float_t  dedx_cm, factor_to_channels, xwire, ywire;
  Float_t sigma_T,sigma_L,diffuse_T,diffuse_L,Ldrift;
  Float_t sigmadel_T,sigmadel_L;                   // behaviour of residuals
  Float_t y_time,tau,sigma_time,tau_norm,tshift;
  Float_t y_low,y_high,tnorm,pnorm,edge_low,edge_high,qpad,qbin;
  Int_t i;
  Int_t irow,ihit,ixmin,ixmax,min_time,max_time,ipad,itime;

  /*
  // Trying numerical integration for Gong response
  Float_t diffused_array[fNbuckets*10];
  Float_t shaped_array[fNbuckets*10];
  Float_t final_array[fNbuckets*10];
  Float_t shaper_lookup_array[fNbuckets*10];
  */
 
  BrDetectorParamsTPC *par;
  Int_t NumHits;
  BrGeantHit* ghit_p;
  if(DebugLevel()>0){ 
    printf("Inside Digitize of %sn",GetName());;
    if(DebugLevel()>0) InputTable->ListObjects();
  }
  par = GetDetectorParamsTPC();
  if(0 == par){
    Warning("Event","Detector Parameters not set for %s",GetName());
    return ;
  }
  if( DebugLevel() > 2){
    cout << " Getting Parameters" << endl;
    par->ListParameters();
  }
  // Decode the inputtable
  //
  Char_t TableName[32];
#ifndef OLD_CDAT_VERSION
  sprintf(TableName,"GeantHits %s", GetName());
#else
  sprintf(TableName,"GeantHits %sPR", GetName());
#endif
  fGeantHits = InputTable->GetDataTable(TableName);
  
  if(fGeantHits == 0 ) {
    if(DebugLevel() > 0){
      cout << "No Table " << TableName << " : " << GetName() << endl;
    }
    return;
  }
  
  NumHits = fGeantHits->GetEntries();
  if(NumHits == 0 ) {
    if(DebugLevel() > 0){
      cout << "No Hits in " << TableName << " :"  << GetName() << endl;
    }
    return;
  }
  
  /*
  cout << " About to fill hist  hNGeantHits! " << endl;
  cout << " NumHits: " << NumHits << endl;
  if (!hNGeantHits) cout << " Histogram does not exist! " << endl;
  */
  if (HistOn()){
    hNGeantHits->Fill(NumHits);
  }
  //  cout << " Filled hist  hNGeantHits! " << endl;
 
  //
  // ObjectList returns TObjectArray
  // Prepare the output table
  //
  sprintf(TableName,"TPCSequence %s",GetName());
  BrDataTable *SequenceTPC = new BrDataTable(TableName,"Sim");
  OutputTable->AddObject(SequenceTPC);
  
  time_bucket = par->GetTimeBucket();
  Anode_Gap   = par->GetAnodeGap();
  sigma_0     = par->GetShapingTime() /2.36;
  sigma_prf   = par->GetAnodeGap();
  tau = fTauScale*par->GetShapingTime();
  //  tshift = fTshift*tau;

  if (DebugLevel()>0) cout << " tau = " << tau << endl;
  
  // Calculate shaper lookup array
  Float_t shaper_integral = 0.0;
  Float_t shaper_centroid = 0.0;
  for (Int_t ifine=0; ifine<100; ifine++){
    Float_t finetime = (Float_t)ifine*0.1*par->GetTimeBucket(); // in ns
    Float_t arg = finetime/tau;
    fShaper_lookup_array[ifine] = arg*arg*BrMath::Exp(-1.*arg);
    shaper_integral += fShaper_lookup_array[ifine]*0.1*par->GetTimeBucket();
    shaper_centroid += fShaper_lookup_array[ifine]*0.1*par->GetTimeBucket()*ifine*0.1*par->GetTimeBucket();
    if (DebugLevel()>2) cout << ifine << " Time: " << finetime << " Shape: " << fShaper_lookup_array[ifine] << endl;
  }
  shaper_centroid /= shaper_integral;
  if (DebugLevel()>2) cout << " Shaper integral: " << shaper_integral << " Centroid: " << shaper_centroid << endl;
  for (Int_t ifine=0; ifine<100; ifine++){
    // Renormalize to integral 1
    fShaper_lookup_array[ifine] = fShaper_lookup_array[ifine]/shaper_integral;
    if (HistOn()) hShapeResp->Fill(ifine,fShaper_lookup_array[ifine]);
  }
  

  factor_to_channels = par->GetADCGain() * par->GetADCChannels() /  
    (Float_t)1024.;

  for(int actrow = 1; actrow <= par->GetNumberOfActiveRows(); actrow++) { 
    irow = par->GetActiveRowNumber(actrow);
    
   Int_t NoTests = 0;
   
	  {
    for(int pad=0;pad<fNpads;pad++)
      for(int time=0;time<fNbuckets;time++)
	fAdcVal[pad][time]=0.0;
	  }
 
    for(ihit=0;ihit<NumHits;ihit++) {
      ghit_p = (BrGeantHit*)fGeantHits->At(ihit);
      if( irow == ghit_p->Isub()) {
	ax = ( ghit_p->LocalPosOut()[0] - ghit_p->LocalPosIn()[0] ) / 
	  ( ghit_p->LocalPosOut()[2] - ghit_p->LocalPosIn()[2] );
	ay = ( ghit_p->LocalPosOut()[1] - ghit_p->LocalPosIn()[1] ) / 
	  ( ghit_p->LocalPosOut()[2] - ghit_p->LocalPosIn()[2] );
	
	
	path_length = (Float_t)0.0;
	for(i=0;i<3;i++)
	  path_length += 
	    (Float_t)pow(ghit_p->LocalPosOut()[i]-ghit_p->LocalPosIn()[i],2.);
	path_length = (Float_t)sqrt(path_length);
	dedx_cm = ghit_p->Dedx() / path_length;
	  
	z = (ghit_p->LocalPosOut()[2] 
	     + ghit_p->LocalPosIn()[2]) / (Float_t)2.0;

	//	dxt = par->GetPadLength() * BrMath::Abs(ax) / (Float_t)2.;
	//	dxl = par->GetPadLength() * BrMath::Abs(ay) / (Float_t)2.;
	// Reproduce behaviour of tracks with large slope
        // Division with 2 - apparent bug
	dxt = par->GetPadLength() * BrMath::Abs(ax);
	dxl = par->GetPadLength() * BrMath::Abs(ay);
	
	
	xc = ghit_p->LocalPosIn()[0] 
	  + ax * ( z - ghit_p->LocalPosIn()[2] );
	yc = ghit_p->LocalPosIn()[1] 
	  + ay * ( z - ghit_p->LocalPosIn()[2] );
	Ldrift = par->IntrinsicToDrift(yc);
	
	diffuse_T = par->GetDtrans() * BrMath::Sqrt( (Double_t)Ldrift+2. );
	diffuse_L = par->GetDlong()  * BrMath::Sqrt( (Double_t)Ldrift+2. );
	
	// As a temporary solution to the problem of angled tracks,
	// fold in the sigma of the square response of ax and ay
	// Treatment of residuals according to formulae:
        // del_T**2 = diffuse_T**2/(padlength*n0) + dxt**2/(12.*n0_per_pad)
        // del_L**2 = diffuse_L**2/(padlength*n0) + dxl**2/(12.*n0_per_pad)
   
	if (fUseGongTimeResp){
	  sigma_L = (Float_t)sqrt( diffuse_L*diffuse_L + dxl*dxl/(Float_t)12.);
	  // Increase sigmadel_L!
          sigmadel_L = diffuse_L*diffuse_L/par->GetPadLength();
	  //  cout << " Sigmadel_L 1: " << sigmadel_L;
	  sigmadel_L += tau*tau*par->GetDriftv()*par->GetDriftv()/par->GetPadLength();
	  //  cout << " Sigmadel_L 2: " << sigmadel_L;
  	  sigmadel_L += dxl*dxl*fN0_pad_to_tot/(Float_t)12.;
	  //  cout << " Sigmadel_L 3: " << sigmadel_L; 
	  sigmadel_L = (Float_t)sqrt(sigmadel_L); 
	  //  cout << " Sigmadel_L: " << sigmadel_L << " Sigma_L: " << sigma_L <<  endl;
	  //      sigmadel_L = (Float_t)sqrt( diffuse_L*diffuse_L/par->GetPadLength() + dxl*dxl*fN0_pad_to_tot/(Float_t)12.);  // for residuals
	} else {
	  sigma_L = (Float_t)sqrt(pow(sigma_0*par->GetDriftv(),2) 
				+ diffuse_L*diffuse_L);
	  sigmadel_L = (Float_t)sqrt( sigma_L*sigma_L/par->GetPadLength() + dxl*dxl*fN0_pad_to_tot/(Float_t)12.);  // for residuals
	  sigma_L = (Float_t)sqrt( sigma_L*sigma_L + dxl*dxl/(Float_t)12.);
	}

	sigma_T = (Float_t)sqrt(sigma_prf*sigma_prf             
				+ diffuse_T*diffuse_T);
	sigmadel_T = (Float_t)sqrt( sigma_T*sigma_T /par->GetPadLength() + dxt*dxt*fN0_pad_to_tot/(Float_t)12.);  // for residuals
	//	cout << " Sigmadel_T: " << sigmadel_T << " Sigma_T: " << sigma_T << endl;
	sigma_T = (Float_t)sqrt( sigma_T*sigma_T + dxt*dxt/(Float_t)12.);
        sigma_time = sigma_L/par->GetDriftv();
        tau_norm = sigma_time/tau;	

	if (HistOn()) hSigmaTDist->Fill(sigma_T/par->GetPadDistance());
	if (HistOn()) hSigmaLDist->Fill(sigma_time/par->GetTimeBucket());
        if (HistOn()) hSigmaTVsY->Fill(yc,sigma_T/par->GetPadDistance());
	if (HistOn()) hSigmaLVsY->Fill(yc,sigma_time/par->GetTimeBucket());
	if (HistOn()) hSigmaTVsXsl->Fill(ax,sigma_T/par->GetPadDistance());

	if(DebugLevel()>2)
	  cout << par->GetDlong() << " " << Ldrift << " " << diffuse_L << endl;

	/* Use a 3 sigma limit on searching for pads which might
	 * have been hit At this point we have all the cluster
	 * variables needed ax = tan(alpha), ay=tan(lambda) yc =
	 * Ldrift, xc which are positions before evaluating the
	 * diffusion in drifts and response widths
	 */
	n0 = dedx_cm * fDedxTon0;
	n0 *= par->GetPadLength() * (Float_t)sqrt( 1.0 + ax*ax + ay*ay );
	n0 *= BrMath::Exp(-1.*fAbsorp*Ldrift);
	if (HistOn()) hN0Dist->Fill(n0);	
	// Evaluate the position on the Anode wires..
	xwire = par->IntrinsicToDistance(xc);
	ywire = Ldrift;
	
	// Distribute signal according to n0 on the Pad
	gRandom->Rannor(a,b);
	//	xwire += sigma_T / (Float_t)BrMath::Sqrt(n0) * a;
	//	ywire += sigma_L / (Float_t)BrMath::Sqrt(n0) * b;
	xwire += sigmadel_T / (Float_t)BrMath::Sqrt(n0) * a;
	ywire += sigmadel_L / (Float_t)BrMath::Sqrt(n0) * b;
	if (HistOn()) hSigmaTRes->Fill(sigmadel_T / (Float_t)BrMath::Sqrt(n0) * a);
	if (HistOn()) hSigmaLRes->Fill(sigmadel_L / (Float_t)BrMath::Sqrt(n0) * b);
	if (HistOn()) hSigmaTResVsY->Fill(yc,BrMath::Abs(sigmadel_T / (Float_t)BrMath::Sqrt(n0) * a));
	if (HistOn()) hSigmaLResVsY->Fill(yc,BrMath::Abs(sigmadel_L / (Float_t)BrMath::Sqrt(n0) * b));
	if (HistOn()) hSigmaTResVsXsl->Fill(ax,BrMath::Abs(sigmadel_T / (Float_t)BrMath::Sqrt(n0) * a));
	if (HistOn()) hSigmaLResVsYsl->Fill(ay,BrMath::Abs(sigmadel_L / (Float_t)BrMath::Sqrt(n0) * b));
        if (HistOn()) hSigmaTResVsN0->Fill(n0,BrMath::Abs(sigmadel_T / (Float_t)BrMath::Sqrt(n0) * a));
        if (HistOn()) hSigmaLResVsN0->Fill(n0,BrMath::Abs(sigmadel_L / (Float_t)BrMath::Sqrt(n0) * b));

	Float_t padxwire = par->IntrinsicToPad(xwire);
	if (HistOn()) hPadCentroid->Fill(padxwire);
        // Evaluate the pad response
	xlo = xwire - (Float_t)3.0 * sigma_T;
        xhi = xwire + (Float_t)3.0 * sigma_T;
	
	if( DebugLevel() > 2) {
	  cout << "Padrow #" << irow <<endl;
	  cout.width(10);
	  cout << "     DT,DL " << setw(8) << diffuse_T 
	       << "," << setw(8)<<diffuse_L << endl;
	  cout << "     n0 " << setw(8)<< n0 << dedx_cm<<fDedxTon0<<endl;
	  cout << "     " << xwire<<" " << xlo << " " << xhi << endl;
	}
     
	//       Find pads which must be looked at.
	
	ixmin = (Int_t) par->DistanceToPad(xlo); //(Int_t)( xlo / par->GetPadDistance() ); // + 1;
	ixmin = BrMath::Max(ixmin,0);
	ixmax = (Int_t) par->DistanceToPad(xhi); // (Int_t)( xhi / par->GetPadDistance() ); // + 1;
	ixmax = BrMath::Min(fNpads-1,ixmax);
	  
	// Pad numbers are counted 0,1,2.. from lower X
	// values. there is the same number of Pads on each side of
	// the centerline  longitudinal Diffusion i.e. along Drift
	// Convert into time buckets. Do fold the response of the
	// shaper into this 
	
	if (fUseGongTimeResp){
	  y_low  = ywire - (Float_t)5.0 * sigma_L;
	  y_high = ywire + (Float_t)10.0 * sigma_L;
	  y_time = par->DriftToTime(irow, ywire);
	} else {
	  y_low  = ywire - (Float_t)3.0 * sigma_L;
	  y_high = ywire + (Float_t)3.0 * sigma_L;
	  y_time = par->DriftToTime(irow, ywire);
	}

	min_time = (Int_t) par->DriftToTime(irow, y_low);
	min_time = BrMath::Max(min_time,0);
	max_time = (Int_t) par->DriftToTime(irow, y_high);
	max_time = BrMath::Min(max_time, fNbuckets-1);
	  
	if( DebugLevel() > 2){
	  cout.width(10);
	  cout << "     " << ixmin << " "<< ixmax << endl;
	  cout << "     " << y_low << " " << y_high << " yc: " << yc << endl;
	  cout << "     " << min_time << " " << max_time << " ytime: " << y_time << endl;
	  cout << " Diffuse_L " << diffuse_L << " Sigma_L " << sigma_L <<  " sigmadel_L " << sigmadel_L << endl;
	  cout << " Sigma_time " << sigma_time << endl;
	}
	  
	tnorm = (Float_t)1. / ( sqtwopi * sigma_L );
	pnorm = (Float_t)1. / ( sqtwopi * sigma_T );

	if (fUseGongTimeResp){
	  // Calculate time response - same for all pads
	  if (DebugLevel()>2) cout << " ytime: " << y_time << " sigma_time: " << sigma_time << endl;
	   
	  for (Int_t ifinetime = 0;ifinetime<=fNbuckets*10;ifinetime++ ) {
	    fDiffused_array[ifinetime] = 0.0;
	    fShaped_array[ifinetime] = 0.0;
	    fFinal_array[ifinetime] = 0.0;
	  }

	  // First calculate Gaussian shape for arriving cluster
	  Float_t original_integral = 0.0;
	  Float_t original_centroid = 0.0;
	  for (Int_t ifinetime = min_time*10;ifinetime<=max_time*10;ifinetime++ ) {
	    Float_t timediff = ((Float_t)ifinetime*0.1 - y_time)*par->GetTimeBucket();	    
	    Float_t timearg = timediff/sigma_time;
	    fDiffused_array[ifinetime] =  BrMath::Exp(-0.5*timearg*timearg)/ (sigma_time*sqtwo);   
	    original_integral += fDiffused_array[ifinetime]*0.1*par->GetTimeBucket();
	    original_centroid += fDiffused_array[ifinetime]*0.1*par->GetTimeBucket()*ifinetime*0.1*par->GetTimeBucket();
	    //  if (NoTests<1) cout << " timediff " << timediff << " diffuse shape " << fDiffused_array[ifinetime] << endl;
	  }

	  original_centroid /= original_integral;
	  //  if (NoTests<10) cout << " Centroid: " << original_centroid << " Integral: " << original_integral << endl;

	  // renormalize Gaussian
	  for (Int_t ifinetime = min_time*10;ifinetime<=max_time*10;ifinetime++ ) {
	    fDiffused_array[ifinetime] = fDiffused_array[ifinetime] / original_integral;
	    Float_t bin_now = (Float_t)(ifinetime)/10.0 - y_time;
	    
	    if (HistOn()) hTimeCluster2D->Fill(bin_now,fDiffused_array[ifinetime]*200);  
	    // if (NoTests<1) cout << " timech " << ifinetime - y_time*10 << " diffuse shape " << fDiffused_array[ifinetime] << endl;
	  }

	  Float_t shaped_integral = 0.0;
	  Float_t shaped_centroid = 0.0;

	  // Fold cluster with shaper response function
	  for (Int_t ifinetime = min_time*10;ifinetime<=(100+max_time*10);ifinetime++ ) {
	    for (Int_t ishape = ifinetime; ishape<ifinetime+100;ishape++ ) {
	      fShaped_array[ishape] += fDiffused_array[ifinetime]*fShaper_lookup_array[ishape-ifinetime]*0.1*par->GetTimeBucket();
;	    
	    }
	  }
;
	  for  (Int_t ifinetime = min_time*10;ifinetime<=(100+max_time*10);ifinetime++ ) {
	    shaped_centroid += fShaped_array[ifinetime]*0.1*par->GetTimeBucket()*ifinetime*0.1*par->GetTimeBucket();
	    shaped_integral += fShaped_array[ifinetime]*0.1*par->GetTimeBucket();	
	  }

	  shaped_centroid /= shaped_integral;

	  //  if (NoTests<10) cout << " Shaped integral: " << shaped_integral << " Centroid: " << shaped_centroid << " Shift: " << shaped_centroid - original_centroid << endl;	  

	  Float_t shift = (shaped_centroid - original_centroid)/(0.1*par->GetTimeBucket());
	  Int_t ishift = (Int_t)shift;
	  Float_t decshift = shift - (Float_t)ishift;
	  //  if (NoTests<10) cout << " Shift " << shift << " Ishift: " << ishift << " Decshift: " << decshift << endl;	  

	  Float_t finalCentroid = 0.0;
	  Float_t finalIntegral = 0.0;
	  for (Int_t ifinetime = min_time*10;ifinetime<=max_time*10;ifinetime++ ) {
	    //  fFinal_array[ifinetime] = (1.0-decshift)*fShaped_array[ifinetime+ishift] + decshift*fShaped_array[ifinetime+ishift+1];
	    fFinal_array[ifinetime] = fShaped_array[ifinetime+ishift] + decshift*(fShaped_array[ifinetime+ishift+1]-fShaped_array[ifinetime+ishift]);
	    finalIntegral += fFinal_array[ifinetime]*0.1*par->GetTimeBucket();
	    finalCentroid += fFinal_array[ifinetime]*0.1*par->GetTimeBucket()*ifinetime*0.1*par->GetTimeBucket();
	    Float_t bin_now = (Float_t)(ifinetime)/10.0 - y_time;
	    
	    if (HistOn()) hTimeShape2D->Fill(bin_now,fShaped_array[ifinetime]*100);  
	    //if (NoTests<1) cout << " timech " << ifinetime - y_time*10 << " Timehape " << fFinal_array[ifinetime] << endl;
    //   if (NoTests<1) cout << " Final array: " << fFinal_array[ifinetime] << " Shaped array: " << fShaped_array[ifinetime]  << endl;
	  }
	  //  if (NoTests<10) cout << " Final integral: " << finalIntegral << " Centroid: " << finalCentroid << endl;	  

	  NoTests++;
	} // if Gong response

	
	Float_t xqsum = 0.0;
	Float_t xpadsum = 0.0;
	for( ipad = ixmin;ipad<=ixmax;ipad++ ) {

	  Int_t Ntests = 0;
	  edge_low  = ((Float_t)ipad + (Float_t).5)*par->GetPadDistance() 
	    - par->GetPadWidth()/(Float_t)2.;
	  edge_high = ((Float_t)ipad + (Float_t).5)*par->GetPadDistance() 
	    + par->GetPadWidth()/(Float_t)2.;
	  if( fUseHyperbolic ) {
	    printf("This part has not been tested yet!!!");
	    qpad = (Float_t)atan((Float_t)sinh(pi*(edge_high-xwire)
					       / (Float_t)2./Anode_Gap))
	      - (Float_t)atan((Float_t)sinh(pi*(edge_low -xwire) /
					    (Float_t)2./Anode_Gap)); 
	    xqsum += qpad;
	    xpadsum += (Float_t)ipad*qpad;
	    if (HistOn()) hPadShape->Fill((Float_t)ipad - padxwire, qpad);
	    if (HistOn()) hPadShape2D->Fill((Float_t)ipad - padxwire, qpad);
	  }
	  else {
	    qpad = pnorm*(Float_t)0.5*(BrMath::Erf((edge_high-xwire)
						   / (sigma_T*sqtwo))
				       - BrMath::Erf((edge_low-xwire) 
						     / (sigma_T*sqtwo)));
	    xqsum += qpad;
	    xpadsum += (Float_t)ipad*qpad;
	    if (HistOn()) hPadShape->Fill((Float_t)ipad - padxwire, qpad);
	    if (HistOn()) hPadShape2D->Fill((Float_t)ipad - padxwire, qpad);
	  }

	  Float_t centroid_test = 0.0;
	  Float_t centroid2_test = 0.0;
	  Float_t integral_test = 0.0;
	  
	  for( itime = min_time;itime<=max_time;itime++ ) {
	       
            if (fUseGongTimeResp){
	    //Try realistic time response

	      Float_t qsum = 0;
	      for (Int_t ifinetime = itime*10-5; ifinetime<(itime*10+5); ifinetime++){
		if (ifinetime>=min_time*10) qsum += fFinal_array[ifinetime]*0.1*par->GetTimeBucket();
	      }
              integral_test += qsum;
	      centroid_test += qsum*itime*par->GetTimeBucket();
	      centroid2_test += qsum*itime*par->GetTimeBucket()*itime*par->GetTimeBucket();
	      //      if (Ntests<1) cout << " itime: " << itime << " qsum: " << qsum << endl;
	      Ntests++;
	      /*
	      Double_t lambda = ((y_time - itime)*par->GetTimeBucket()-tshift)/sigma_time + tau_norm;
	      Double_t arg1 = tau_norm*(lambda - 0.5*tau_norm);	    
	      Double_t fac1 = BrMath::Exp(arg1);
	      Double_t gau1 = BrMath::Exp(-0.5*lambda*lambda);
	      gau1 *= lambda/BrMath::Sqrt(2.0*pi);
	      Double_t erf1 = BrMath::Erf(lambda/sqtwo); 
	      Double_t fac2 = (1.0 + lambda*lambda)/2.0*(1 - erf1) - gau1;
	      Double_t timeresp = tau_norm*tau_norm*fac1*fac2;  
	      */
	      Double_t timeresp = qsum;
	      if (HistOn()) hSequenceShape->Fill((Float_t)itime-y_time,timeresp);
	      if (HistOn()) hSequenceShapeY2D->Fill(yc,(Float_t)itime-y_time);
	      if (HistOn()) hSequenceShapeYsl2D->Fill(ay,(Float_t)itime-y_time);
	      qbin = timeresp*qpad*n0;
	    }
	    else {
	    
	      // use Gaussian
	      edge_low  = par->TimeToDrift(itime);
	      edge_high = par->TimeToDrift(itime+1);
	      qbin = (Float_t)0.5 * (BrMath::Erf((edge_high - ywire) /
					       (sigma_L*sqtwo)) -
				   BrMath::Erf((edge_low  - ywire) /
					       (sigma_L*sqtwo)));
	      if (HistOn()) hSequenceShape->Fill((Float_t)itime-y_time,qbin);
	      if (HistOn()) hSequenceShapeY2D->Fill(yc,(Float_t)itime-y_time);
	      if (HistOn()) hSequenceShapeYsl2D->Fill(ay,(Float_t)itime-y_time);
	      qbin *= tnorm * qpad * n0;
	    }
	    //	    cout << " ipad: " << ipad << " itime: " << itime << " qbin: " << qbin << endl; 
            fAdcVal[ipad][itime]+=qbin*factor_to_channels;
	    
	  } //loop over itime
	  centroid_test /= integral_test;
	  centroid2_test /= integral_test;
	  Float_t time_centroid = centroid_test/par->GetTimeBucket();
	  Float_t time_centroid2 = centroid2_test/(par->GetTimeBucket()*par->GetTimeBucket());
	  Float_t timevar = BrMath::Sqrt(time_centroid2-time_centroid*time_centroid);
	  if (HistOn()) hYmiss->Fill(time_centroid-y_time);
	  if (HistOn()) hSigmaLTotDist->Fill(timevar);
	  if (HistOn()) hSigmaLTotVsY2D->Fill(yc,timevar);
	  if (HistOn()) hSigmaLTotVsY->Fill(yc,timevar);
	  if (HistOn()) hSigmaLTotVsYsl->Fill(ay,timevar);
	  if (HistOn()) hSigmaLTotVsYsl2D->Fill(ay,timevar);
	  Float_t y_resulting = par->TimeToIntrinsic(irow,time_centroid);
	  if (HistOn()) hYDistToHit->Fill(y_resulting-yc);
	  //  if (NoTests<10) cout << " Centroid: " << centroid_test << " Integral: " << integral_test << " Ytime: " << time_centroid << endl;
	} // loop over ipad
	Float_t xpadcentroid = xpadsum / xqsum;
	Float_t x_resulting = par->PadToIntrinsic(xpadcentroid);
	if (HistOn()) hXDistToHit->Fill(x_resulting-xc);
      } // correct row
    } // loop over ihit
    //
    // Add noise if fNoise non-zero
    //
    
    if(fNoise>0.0)  {
      for(ipad=0;ipad<fNpads;ipad++)
	for(itime=0;itime<fNbuckets;itime++){
	  gRandom->Rannor(a,b);
	  fAdcVal[ipad][itime]+=a*fNoise;
	}
    }
    
    if(DebugLevel()> 0)
      cout << "Scan for Sequences Row " << irow << endl;
    for(int pad=0; pad<fNpads; pad++) {
      if( ! par->IsPadActive(irow, pad)) continue;
      Bool_t insequence=kFALSE;
      int timebin; int nbins=0;
      for(int time=0; time < fNbuckets; time++){
	if(fAdcVal[pad][time] > fAdcCut){
	  if(insequence){
	    nbins++;
	  }
	  else {
	    nbins=1;
	    timebin = time;
	    insequence=kTRUE;
	  }
	}
	else {
	  if(insequence){
	    //    if(nbins>1){
	    if(nbins>=fMinNbins){
	      BrTpcSequence* seq = new BrTpcSequence(nbins);
	      SequenceTPC->Add(seq);
	      seq->SetRow(irow);
	      seq->SetPad(pad);
	      seq->SetTime(timebin);
	      Short_t* adc = seq->GetSequence();
	      Float_t adcsum = 0.0;
	      Float_t adcbinsum = 0.0;
	      for(int it=0;it<nbins;it++, timebin++){
		Short_t digval = (Short_t) fAdcVal[pad][timebin];
		*adc++ = Short_t ( digval > 1024 ? 1024 : digval);
		if (HistOn()) hAdcDist->Fill(digval);
		adcsum += digval;
		adcbinsum += digval*(Float_t)timebin;
	      }
	      if (HistOn()) hNTimebins->Fill(nbins);
	      Float_t seq_centroid = adcbinsum/adcsum;
	      Float_t seq_cent_dec = seq_centroid - (Int_t)seq_centroid;
	      //   if (DebugLevel()) cout << " Cent: " << seq_centroid << " Dec cent: " << seq_cent_dec << endl;
	      if (HistOn()) hAdcSumDist->Fill(adcsum);
	      if (HistOn()) hSequenceCentroid->Fill(seq_centroid);
	      if (HistOn()) hSequenceCentroidDecimal->Fill(seq_cent_dec);
	      //	      if (HistOn()) hYmiss->Fill(seq_centroid-y_time);
	    }
	    insequence = kFALSE;
	  }
	}
	
      }  // time
      if(insequence){
	// if(nbins>1){
	if(nbins>=fMinNbins){
	  BrTpcSequence*  seq = new BrTpcSequence(nbins);
	  SequenceTPC->Add(seq);
	  seq->SetRow(irow);
	  seq->SetPad(pad);
	  seq->SetTime(timebin);
	  Short_t* adc = seq->GetSequence();
	  Float_t adcsum = 0.0;
	  Float_t adcbinsum = 0.0;
	  for(int it=0;it<nbins;it++, timebin++){
	    Short_t digval = (Short_t) fAdcVal[pad][timebin];
	    *adc++ = Short_t ( digval > 1024 ? 1024 : digval);
	    if (HistOn()) hAdcDist->Fill(digval);
	    adcsum += digval;
	    adcbinsum += digval*(Float_t)timebin;
	  }
	  if (HistOn()) hNTimebins->Fill(nbins);
	  Float_t seq_centroid = adcbinsum/adcsum;
	  Float_t seq_cent_dec = seq_centroid - (Int_t)seq_centroid;
	  //  if (DebugLevel()) cout << " Cent: " << seq_centroid << " Dec cent: " << seq_cent_dec << endl;
	  if (HistOn()) hAdcSumDist->Fill(adcsum);
	  if (HistOn()) hSequenceCentroid->Fill(seq_centroid);
	  if (HistOn()) hSequenceCentroidDecimal->Fill(seq_cent_dec);
	  //	  if (HistOn()) hYmiss->Fill(seq_centroid-y_time);
	}
      }
    }
  }			//loop over irow

  if (HistOn()) hNSequences->Fill(SequenceTPC->GetEntries());

  //Get stuff for statistics
  if(DebugLevel()>0)
    cout << "Total number of sequences " 
	 << SequenceTPC->GetEntries() << endl;
}
    
    
      
  //_________________________________________________________
 void BrDigitizeTPC::DrawGeantHits() {
  //
  // 
  BrDetectorVolume *vol;
  Char_t volbuf[64];
  Char_t canvasname[64];
  Char_t nodename[64];
  TCanvas *canvas;
  
  sprintf(canvasname,"%sCanvas",GetName());
  
  if(!fDetectorNode) {
    canvas = (TCanvas*)gROOT->FindObject(canvasname);
    if(!canvas) canvas = new TCanvas(canvasname,canvasname,50,50,400,400);
    sprintf(volbuf,"TPC %s",GetName());
    vol = GetDetectorVolume();
    sprintf(nodename,"%sDetectorNode",GetName());
    
    fDetectorNode = new BrDetectorTPC(nodename,nodename,GetName()); //vol);
    
    fDetectorNode->Draw();
    TView *view = canvas->GetView();
    
    // Set the view to dimensions we know for TPC's; this could be made more general
    // but following looks pretty good.
    view->SetRange(-35,-35,-35,35,35,35);
    Int_t irep;
    view->SetView(-90,90,0,irep);
    
  }
  
  fDetectorNode->Clear();
  
  canvas = (TCanvas*)gROOT->FindObject(canvasname);
  //Check if canvas still exists; if not, don't draw the hits.
  if(canvas) {
    canvas->cd();
    fDetectorNode->DrawGeantHits(fGeantHits);
  }
}
/////////////////////////////////////////////////////////////////////////////
//
//      $Log: BrDigitizeTPC.cxx,v $
//      Revision 1.5  2001/11/13 21:11:24  trulsml
//      Put if (debuglevel) in front of annoying: cout << "delete index Table" << endl;
//      in the destructor and the Init method.
//
//      Revision 1.4  2001/09/18 19:31:56  trine
//      Improved description of angled tracks and of residuals.
//      Added members for setting:
//      - min. no of bins in a BrTpcSequence
//      - ratio of total no. of electrons / electrons per pad.
//
//      Revision 1.3  2001/08/12 13:32:58  cholm
//      Changed CTOR prototype to comply with BrModule CTOR (const Char_t*'s instead
//      of just Char_t*'s).
//
//      Revision 1.2  2001/06/22 17:40:08  cholm
//      Changes t odo with data classes renaming.
//
//      Revision 1.1.1.1  2001/06/21 14:55:06  hagel
//      Initial revision of brat2
//
//      Revision 1.40  2001/06/19 18:57:43  trine
//      Added possibility to use more realistic time response taken from
//      Gong's STAR note, instead of Gaussian default.
//      Moved calculation of "residuals" to after place in code where track
//      slopes are folded into cluster widths.
//
//      Revision 1.38  2001/04/18 20:19:42  videbaek
//      initilaize fAdcVal in constructor
//
//      Revision 1.37  2000/11/22 21:22:35  videbaek
//      Modified for Init handling.
//      Some cosmetic changes.
//
//      Revision 1.36  2000/10/02 17:07:56  pchristi
//      Cleaned up headers and source files in the tpc dir
//
//      Revision 1.35  2000/09/07 20:05:29  videbaek
//      Add methods for row setting, and Modified to proper row numbers 1,2...
//
//      Revision 1.34  2000/09/04 14:58:40  videbaek
//      Add some redundant block brackets to  make VC++6.0 happy.
//
//      Revision 1.33  2000/08/28 18:05:54  videbaek
//      Move CVS log to end of file
//
//      Revision 1.32  2000/08/28 00:18:45  videbaek
//      Added calibration parameter to Detectorparams, to deal better with time-distance conversion
//      in TPCs. Added row dependent conversion too.
//
//      Revision 1.31  2000/04/28 21:22:13  videbaek
//      Add new classes for TPC. Many changes and not completely debugged.
//      Note that the old method BrTPCLocaltracking has been tested to work.
//
//      Revision 1.30  2000/03/21 21:22:34  cholm
//      Several changes: A few hacks where needed to compile on Digital Unix, noticably in my - Christian Holm - classes for the DB and Exceptions. Proberly still need to do something to some of Konstantins stuff. Also, I removed a lot of warnings fromt the compiler, by teddying up the code. Several places, old C-style indecies in for loops were assumed. Corrected. Unused variables have been commented out.
//
//      Revision 1.29  2000/01/18 18:39:54  videbaek
//      Moved covariance array form fit to calling parameter.
//      lized and checkout of digitization, reconstruction code.
//      Added (possible noise ) to digitization. Changed default value of
//      dedxton0. Made it parameter in DetectorParamsTPC
//
//      Revision 1.28  2000/01/04 21:49:38  videbaek
//      start adding dynamic arrays rather than fixed size.
//      Change cluster size max to deal with noisy cosmic ray events.
//
//      Revision 1.27  1999/12/30 19:45:00  videbaek
//      Code changes to use the intrinsic cocrdinates consistently.
//
//      Revision 1.26  1999/12/18 21:37:42  videbaek
//      Obsolete for a long timeBrDigTTPC.cxx
//
//      Revision 1.25  1999/08/14 17:01:59  videbaek
//      Updates for
//      a) RawData adding the Trigger TDCs'
//      b) Implied new data objects BrTrigBB
//      c) Clean up of TPC code
//      d) Test MyMonitor and scripts
//
//      Revision 1.24  1999/03/09 18:38:34  videbaek
//      Minor fixes. Now a proper working version. Included dependeces in
//      Makefile. Added some member function to the tracking class, and
//      minor updates.
//
//      Revision 1.23  1999/03/07 23:28:26  hagel
//      Slight modifications in SetDetectorParamsTPC to prevent crashing if user
//      uses it since BrParameterDbManager is implemented.
//
//      Revision 1.22  1999/03/07 00:00:45  hagel
// 
//
//      Revision 1.21  1999/02/28 22:14:38  hagel
//      Changes to make event display more robust and seamless
//
//      Revision 1.20  1999/02/25 14:53:16  videbaek
//      Inserted code for using BrTPCSequnece instead of BrDigTPC for both
//      TPC digitization and the TPC local track reconstruction.//
//      Revision 1.19  1999/01/28 21:28:13  videbaek
//       Added BrTPSSqquences to libraries. Not yet in use, though. Expected to
//      replace BrDigTPC objects
//       Added cvs flags
//       Changed name of BrDigTPC data tables.
//
//      Revision 1.18  1999/01/15 16:35:48  videbaek
//      Changes included using clonesarrays in digitizations.
//      Localtracking added cuts for type 4 clusters
//
//      Revision 1.17  1999/01/06 23:08:04  hagel
//      Add support for DrawGeantTracks in Digitize
//
//      Revision 1.16  1998/12/21 20:27:41  videbaek
//      Improved geometry for MTP1 and MTP2
//
//      Revision 1.14  1998/10/09 19:23:59  videbaek
//      Add some diagnostics output
//
//      Revision 1.13  1998/09/27 17:11:02  alv
//      removed EventStatisticsStart and EventStatisticsEnd
//      (inherit them from BrModule)
//      In ListEventStatistics
//        used BrModule::ListEventStatistics to list CPU time
//
//      Revision 1.12  1998/09/18 20:37:40  videbaek
//      veMove SetRowPosition from being inline
//
//      Revision 1.11  1998/09/16 20:17:26  alv
//      In constructors
//       Added fParams_p=0 and fVolumeParams_p=0
//      In SetDetectorParamsTPC
//       Protected against delete of par
//       Used copy constructor insted of new+assignment
//      In Event
//       Removed embedded x0 in format string of sprintf
//       Removed unused variables twopi and sqpi
//
//      Revision 1.10  1998/08/05 19:34:27  hagel
//      Fix BrDigTPC memory leak
//
//      Revision 1.9  1998/07/02 13:58:43  videbaek
//       comment updates mainly
//
//      Revision 1.8  1998/05/14 21:18:15  videbaek
//      update makefile - do not reload .so libraries
//
//      Revision 1.7  1998/05/13 20:30:50  hagel
//      Changes to compile under Solaris
//
//      Revision 1.6  1998/05/08 20:45:56  videbaek
//      TPC class updates; added functionality
//
//      Revision 1.5  1998/05/08 00:58:43  videbaek
//      TPC code updates
//
//      Revision 1.4  1998/04/30 16:40:48  hagel
//      Changes to work with new version of GBRAHMS
//
//      Revision 1.3  1998/04/06 21:12:00  videbaek
//      Clean up and additions for Win95
//
//	Revision 1.2  1998/04/01 22:08:36  hagel
//	Add Local tracking and fix bugs in Digitization
//
//	Revision 1.1.1.1  1998/03/04 21:34:03  brahmlib
//	Brat tpc
//
//

This page automatically generated by script docBrat by Christian Holm

Copyright ; 2002 BRAHMS Collaboration <brahmlib@rcf.rhic.bnl.gov>
Last Update on by

Validate HTML
Validate CSS