BRAT 2.4.5
Class index
Full class index
brahmlib
BRAHMS
ROOT page
//____________________________________________________________________
//
//   The BrTpcClusterModule is used to group the sequences into
//   clusters, and store the clusters in a cluster table.
//   This Class has been taken from what M. Justice  started to put
//   together in Oct 99 
// 
//   It takes sequences that have been filtered with
//   BrTPCPreProcess as input and groups the sequences into
//   BrTpcCluster s 
//
//   Deconvolution has been moved to BrTpcDeconvoluteClusterModule
//

//____________________________________________________________________
//
// $Id: BrTpcClusterModule.cxx,v 1.8 2002/06/13 18:46:33 videbaek Exp $
// $Author: videbaek $
// $Date: 2002/06/13 18:46:33 $
// $Copyright: (C) 2001 BRAHMS Collaboration <brahmlib@rhic.bnl.gov>
//

#include <BrTpcClusterModule.h>

#ifndef WIN32
#include <iostream>
#else
#include <iostream.h>
#endif
#include <iomanip.h>

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

#ifndef BRAT_BrTableNames
#include "BrTableNames.h"
#endif

//__________________________________________________________________ 

ClassImp(BrTpcClusterModule);

//__________________________________________________________________
 BrTpcClusterModule::BrTpcClusterModule()
  : BrModule() 
{
  // This constructer is no good
  SetState(kSetup);

  fClusterTable = 0;
  fSeqTable     = 0;
  fReset        = kFALSE;
}

//__________________________________________________________________
 BrTpcClusterModule::BrTpcClusterModule(const Char_t *name, 
				       const Char_t *title) 
  : BrModule(name, title)
{
  // This is the constructor that should be used
  // Name should be "T1", "T2", "TPM1", "TPM2"
  SetState(kSetup);

  fClusterTable = 0;
  fSeqTable     = 0;
  fReset        = kFALSE;
}

//_________________________________________________________________
 BrTpcClusterModule::~BrTpcClusterModule()
{
  // empty
}

//_________________________________________________________________
 void BrTpcClusterModule::DefineHistograms()
{
  // Define the histograms used to monitor performance
  // This method is usually called by BrModule::Book().
  //
  
  // Initialiser at job level
  if (GetState() != kInit) {
    Stop("DefineHistograms", "Must be called after Init");
    return;
  }
  
  // Create new subdirectory for histograms
  TDirectory* savdir = gDirectory;
  Char_t Dirname[32];
  sprintf(Dirname,"Cluster_%s",GetName());
  TDirectory* hdir = savdir->mkdir(Dirname);
  
  if (!hdir) {
    Warning("DefineHistograms","Could not create histogram subdirectory");
    return;
  }
  hdir->cd();

  Char_t Histname[32];
  Char_t HistTitle[48];
   
  sprintf(Histname,"hNpads_%s",GetName());
  sprintf(HistTitle,"%s: # pads per cluster",GetName());
  hNpads = new TH1F(Histname, HistTitle,20,0.5,20.5);
  hNpads->SetXTitle( "N_{pads}" );
  hNpads->SetYTitle( "dN/dN_{pads}" );

  sprintf(Histname,"hNtimebins_%s",GetName());
  sprintf(HistTitle,"%s: # time bins per cluster",GetName());
  hNtime = new TH1F(Histname, HistTitle,20,0.5,20.5);
  hNtime->SetXTitle( "N_{time bins}" );
  hNtime->SetYTitle( "dN/dN_{time bins}" );
   
  sprintf(Histname,"hNclusters_%s",GetName());
  sprintf(HistTitle,"%s: # clusters per event",GetName());
  hNclusters = new TH1F(Histname, HistTitle,800,-0.5,799.5);
  hNclusters->SetXTitle( "N_{clusters}" );
  hNclusters->SetYTitle( "dN/dN_{clusters}" );
   
  sprintf(Histname,"hMaxADC_%s",GetName());
  sprintf(HistTitle,"%s: max ADC in clusters",GetName());
  hMaxADC = new TH1F(Histname, HistTitle,1024,0.5,1024.5);
  hMaxADC->SetXTitle( "ADC_{max}" );
  hMaxADC->SetYTitle( "dN/dADC_{max}" );

  sprintf(Histname, "hSumADC_%s", GetName());
  sprintf(HistTitle, "%s: integrated ADC in clusters", GetName());
  hSumADC = new TH1F(Histname, HistTitle, 1024, 0., 10240);
  hSumADC->SetXTitle( "ADC_{sum}" );
  hSumADC->SetYTitle( "dN/dADC_{sum}" );

  sprintf(Histname,"hPadvar_%s",GetName());
  sprintf(HistTitle,"%s: pad sigma",GetName());
  hPadvar = new TH1F(Histname, HistTitle,40,0.0,10.0);
  hPadvar->SetXTitle( "#sigma_{pad} [pads]" );
  hPadvar->SetYTitle( "dN/d#sigma_{pad}" );

  sprintf(Histname,"hTimevar_%s",GetName());
  sprintf(HistTitle,"%s: time sigma",GetName());
  hTimevar = new TH1F(Histname, HistTitle,40,0.0,10.0);
  hTimevar->SetXTitle( "#sigma_{time bin} [time bin]" );
  hTimevar->SetYTitle( "dN/d#sigma_{time bin}" );

  // Restore directory
  savdir->cd();
}

//_______________________________________________________________________
 void BrTpcClusterModule::Init() 
{
  // Initialize module. Empty.
  SetState(kInit);
}

//_________________________________________________________________
void 
 BrTpcClusterModule::Event(BrEventNode *inputNode, 
			  BrEventNode *outputNode)
{ 
  // Main method
  // Gets the TPCSequence data from the inputNode
  // Group the sequences into clusters.
  // Output the clusters on outputNode
  SetState(kEvent);

  if(DebugLevel()>2)
    cout << "Entering " << GetName() 
	 << "BrTpcClusterModule Event()" << endl;
  
  fSeqTable = 
    inputNode->GetDataTable(Form("%s %s", BRTABLENAMES kTPCSequence, GetName()));
  
  if(fSeqTable == 0) {
    
    if(DebugLevel() > 0 ) 
      Warning("Event", "BrDataTable %s %s not found in this event!",
	      BRTABLENAMES kTPCSequence, GetName());
    
    return;
  }

  // Sort the datatable using the method 
  // BrTpcSequence::Compare(const TObject*) const
  // This makes it easier to group the data
  fSeqTable->Sort();

  // Create the output node
  fClusterTable = new BrDataTable(Form("%s %s", BRTABLENAMES kTPCCluster, GetName()));


  FindClusters();
  
  // Append output data to output event node
  outputNode->AddDataTable(fClusterTable);

  if ( fReset ) ResetSequenceTable();
}

//__________________________________________________________________
 void BrTpcClusterModule::ResetSequenceTable()
{
  // Reset BrTpcSequence::fClustNum to -1, as this variable is modified in FindClusters.

  if ( !fSeqTable ) return;

  Int_t nSeq = fSeqTable->GetEntries();

  if ( !nSeq ) return;

  for ( Int_t iS = 0; iS < nSeq; iS++ ) 
    ((BrTpcSequence*) fSeqTable->At( iS ))->SetClustNum( -1 );
}

//__________________________________________________________________
 Bool_t BrTpcClusterModule::FindClusters()
{
  // **************************************************************
  // *                                                            *
  // *  The algorithm used here is to group together sequences    *
  // *  on adjacent pads which overlap in the temporal direction  *
  // *  as determined by the SeqOverlap function                  *
  // *                                                            *
  // **************************************************************
  
  BrTpcCluster *currCluster = 0;
  
  fClusterId = 0;
  
  const Int_t nSeq = fSeqTable->Entries();

  Debug(3,"Find Clusters","Entry - Total sequences %d",nSeq);

  for (Int_t i = 0; i < nSeq; i++) {
    
    BrTpcSequence *iseq = (BrTpcSequence*) fSeqTable->At(i);
    Int_t irow     = iseq->GetRow();
    Int_t ipad     = iseq->GetPad();
    Int_t iclustID   = iseq->GetClustNum();
    
    // If the cluster id is < 0 it does not belong to a cluster
    if (iclustID < 0) {
      
      iclustID = fClusterId++;
      iseq->SetClustNum( iclustID ); 

      // make a new cluster
      currCluster = new BrTpcCluster(irow, *iseq);
      fClusterTable->Add(currCluster);
      currCluster->SetID(iclustID);
      
      if(DebugLevel()>5) {
	
	cout << "New Cluster for Sequence " << i << " / " << nSeq 
	     << "n Row " << irow << " - Pad " << ipad 
	     << "n ID " << iclustID << endl;
      }
      
    } else {
      
      currCluster = GetClusterById(iclustID);
      Assert( currCluster );
      
      if(DebugLevel()>3) {
	cout << "Sequence " << i << " / " << nSeq 
	     << " : old cluster ID " << iclustID << endl;
	currCluster->Print();
      }
    }

    for (Int_t j = (i+1); j < nSeq; j++) {
      
      BrTpcSequence *jseq = (BrTpcSequence*) fSeqTable->At(j);
      Int_t jrow   = jseq->GetRow();

      // if we are in the next row stop looking 
      // (we have sorted the table)
      if( jrow != irow ) 
	break;

      Int_t jpad   = jseq->GetPad();

      if( jpad != (ipad+1) ) 
	continue;

      if(DebugLevel()>5)
	cout << " Check seq("<<j<<") : " << jseq->GetClustNum() << ", pad = "
	     << jseq->GetPad() << " overlap" << endl;
      
      if ( SeqOverlap(iseq, jseq) ) {

	Int_t jclustID = jseq->GetClustNum();

	if ( DebugLevel()>3 ) 
	  cout << "Cluster ID for overlapping sequence : " 
	       << jclustID << endl;

	// If the sequence does not belong to a cluster
	if (jclustID == -1) {

	  // add sequence
	  jseq->SetClustNum( iclustID );	
	  currCluster->AddSeq( *jseq );
	  
	  if(DebugLevel()>3)
	    cout << " Add Sequence " << jseq->GetClustNum()<<" in pad " <<jpad 
		 << "to cluster" << endl; 

	  //
	  // If the sequence already belongs to a cluster (but not icluster)
	  // add whole jcluster to icluster and delete jcluster 
	} else if ( jclustID != iclustID ) {

	  if(DebugLevel()>3){
	    cout << " Add old cluster : " << setw(4) << jclustID
		 << " to cluster : " << setw(4) << iclustID; 
	  }
	  
	  BrTpcCluster *clustOld = GetClusterById(jclustID);
	  // test that cluster old exists
	  Assert( clustOld );
	  
	  TObjLink *lnk = clustOld->GetSeqList()->FirstLink();
	  while ( lnk ) {

	    BrTpcSequence *seqOld = (BrTpcSequence*)lnk->GetObject();
	    // have to set same ID for the sequence in the BrDataTable
	    BrTpcSequence *tabSeq =
	      (BrTpcSequence*)fSeqTable->GetObjectList()
	      ->FindObject( seqOld );
	    // test that we do get the right sequence
	    Assert( tabSeq );
	    Assert( tabSeq->IsEqual(seqOld) );

	    tabSeq->SetClustNum( iclustID );
	    currCluster->AddSeq( *tabSeq ); // make a copy
	    lnk = lnk->Next();
	  }

	  // Finally we remove the old cluster
	  fClusterTable->DeleteAndCompress(clustOld);
	  Assert(GetClusterById(jclustID) == 0 ); 
	} 
      } 
    } 
  }
  
  if(DebugLevel()>0)
    cout << "Number of clusters in TPC " << GetName() 
	 << " = " << fClusterTable->GetEntries() << endl;

  // Fill histograms
  if(HistOn()) {
    const Int_t nEnt = fClusterTable->GetEntries();
    
    hNclusters->Fill(nEnt);
    
    for(Int_t n = 0; n < nEnt; n++) {
      
      BrTpcCluster *cluster = (BrTpcCluster *)fClusterTable->At(n);
      hNpads->Fill(cluster->GetNpads());
      hNtime->Fill(cluster->GetNbins());
      hMaxADC->Fill(cluster->GetMaxADC());
      hSumADC->Fill(cluster->GetADCSum());
      hPadvar->Fill(cluster->GetVarPad());
      hTimevar->Fill(cluster->GetVarTime());
    }
  }

  return kTRUE;
}

//__________________________________________________________________________
 BrTpcCluster* BrTpcClusterModule::GetClusterById(Int_t id) 
{
  // Loop over fClusterTable and return cluster with matching id
  // If cluster is not found return 0
  
  const Int_t nEntries = fClusterTable->GetEntries();
  
  // do the loop counting down since it is most likely to be close to
  // the end = this row
  for(Int_t i = nEntries-1; i >=0; i--) {
    
    BrTpcCluster *cluster = 
      (BrTpcCluster *) fClusterTable->At(i);
    
    if(cluster->GetID() == id)
      return cluster;
    
  }
  
  return 0;
}
  
//____________________________________________________________________
 void BrTpcClusterModule::Print(Option_t* option) const
{ 
  // Module Information method
  //
  // Options: (see also BrModule::Print)
  //  
  BrModule::Print(option);

  TString opt(option);
  opt.ToLower();
  
  if (opt.Contains("d"))
   cout << endl
         << "  Original author: Peter H.L. Christiansen" << endl
         << "  Last Modifications: " << endl
         << "    $Author: videbaek $" << endl 
         << "    $Date: 2002/06/13 18:46:33 $"   << endl
         << "    $Revision: 1.8 $ " << endl 
         << endl
         << "-------------------------------------------------" << endl;

} 

//__________________________________________________________________________
 Bool_t BrTpcClusterModule::SeqOverlap(BrTpcSequence *iseq, 
				      BrTpcSequence *jseq)
{
  //   ***************************************************************
  //   *                                                             *
  //   * Overlap criteria:                                           *
  //   *                                                             *
  //   *                  |                    |                     *
  //   *                  |                    |                     *
  //   *        TRUE      |           FALSE    |                     *
  //   *                  | |                  |                     *
  //   *                  | |                  | |                   *
  //   *                    |                    |                   *
  //   *                    |                    |                   *
  //   *                                         |                   *
  //   *                                         |                   *
  //   *                                                             *
  //   *     This could be made more flexible by introduction        *
  //   *     of a parameter controlling the amount of overlap        *
  //   *     required.                                               *
  //   *                                                             *
  //   ***************************************************************
  //
  // Maybe this method should be in the BrTpcSequence
  
  Int_t ifirst = iseq->GetTime();
  Int_t ilast  = ifirst + iseq->GetNseq()-1;
  Int_t jfirst = jseq->GetTime();
  Int_t jlast  = jfirst + jseq->GetNseq()-1;
  
  if ( ( (jfirst > ifirst)  && (jfirst < ilast) )  ||
       ( (jlast  > ifirst)  && (jlast  < ilast) )  ||
       ( (ifirst > jfirst)  && (ifirst < jlast) )  ||
       ( (ilast  > jfirst)  && (ilast  < jlast) )  ||
       ( (ifirst == jfirst) && (ilast == jlast) ) ){
    
    return kTRUE;
  } else {
    
    return kFALSE;
  }
}

////////////////////////////////////////////////////////////////////////////
//
// $Log: BrTpcClusterModule.cxx,v $
// Revision 1.8  2002/06/13 18:46:33  videbaek
// add debug information
//
// Revision 1.7  2002/01/03 19:53:11  cholm
// Prepared to use BrTableNames class (or perhaps BrDetectorList) for table names
//
// Revision 1.6  2001/08/16 15:45:17  jens
//
// BrTpcClusterModule
// BrTpcDeconvoluteClusterModule
// BrTpcTrackModule
// Changed some variable names for histograms and the title scheme for histogram.
// Now histograms have title like e.g. "<TPC name>: max ADC in clusters".
//
// BrTpcClusterModule
// Added the possibility to reset sequences in fSeqTable. BrTpcSequence::fClustNum
// is altered in BrTpcClusterModule::FindClusters, and thus made it impossible to
// reanalyze an event. I.e. previously a new instance of BrEvent had to be
// allocated and filled from input.
//
// Revision 1.5  2001/08/14 19:29:33  pchristi
// Changed the Print methods to pass the option to BrModule.
// Also removed debug statement in BrTpcTrackFollowModule.
//
// Revision 1.4  2001/07/06 10:23:48  pchristi
// Changed assert to the ROOT Assert in TError.h
//
// Revision 1.3  2001/06/25 14:40:58  cholm
// Use BrTpcCluster::Print rather than BrTpcCluster::List
//
// Revision 1.2  2001/06/22 17:45:14  cholm
// Change names so that every data class has the same format, so that
// we will not have to worry about that later on. The affected classes
// are:
//
//         BrTPCSequence       ->        BrTpcSequence
//         BrTPCCluster        ->        BrTpcCluster
//         BrTPCClusterTable   ->        BrTpcClusterTable
//
// These changes has ofcourse been propegated to the modules as well,
// giving the changes
//
//         BrTPCClusterFinder  ->        BrTpcClusterFinder
//         BrTPCSequenceAdder  ->        BrTpcSequenceAdder
//
// Revision 1.1.1.1  2001/06/21 14:55:13  hagel
// Initial revision of brat2
//
// Revision 1.2  2001/06/17 17:29:33  pchristi
// Near final version. A little cosmetics is still needed.
//
// Revision 1.1  2001/05/29 14:20:17  pchristi
// Initial import of new Tpc classes
//
//

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