// @(#) $Id$ // Author: Anders Vestbo , // Constantin Loizides // Jochen Thaeder //*-- Copyright © ALICE HLT Group #include "AliHLTTPCDigitReader.h" #include "AliHLTTPCStandardIncludes.h" #include "AliHLTTPCRootTypes.h" #include "AliHLTTPCLogging.h" #include "AliHLTTPCClusterFinder.h" #include "AliHLTTPCDigitData.h" #include "AliHLTTPCTransform.h" #include "AliHLTTPCSpacePointData.h" #include "AliHLTTPCMemHandler.h" #if __GNUC__ >= 3 using namespace std; #endif /** \class AliHLTTPCClusterFinder
//_____________________________________________________________
// AliHLTTPCClusterFinder
//
// The current cluster finder for HLT
// (Based on STAR L3)
// 
// The cluster finder is initialized with the Init function, 
// providing the slice and patch information to work on. 
//
// The input is a provided by the AliHLTTPCDigitReader class,
// using the init() funktion, and the next() funktion in order 
// to get the next bin. Either packed or unpacked data can be
// processed, dependent if one uses AliHLTTPCDigitReaderPacked 
// class or AliHLTTPCDigitReaderUnpacked class in the 
// Clusterfinder Component.
// The resulting space points will be in the
// array given by the SetOutputArray function.
// 
// There are several setters which control the behaviour:
//
// - SetXYError(Float_t):   set fixed error in XY direction
// - SetZError(Float_t):    set fixed error in Z  direction
//                            (used if errors are not calculated) 
// - SetDeconv(Bool_t):     switch on/off deconvolution
// - SetThreshold(UInt_t):  set charge threshold for cluster
// - SetMatchWidth(UInt_t): set the match distance in 
//                            time for sequences to be merged 
// - SetSTDOutput(Bool_t):  switch on/off output about found clusters   
// - SetCalcErr(Bool_t):    switch on/off calculation of 
//                          space point errors (or widths in raw system)
// - SetRawSP(Bool_t):      switch on/off convertion to raw system
//
//
// Example Usage:
//
// AliHLTTPCFileHandler *file = new AliHLTTPCFileHandler();
// file->SetAliInput(digitfile); //give some input file
// for(int slice=0; slice<=35; slice++){
//   for(int patch=0; pat<6; pat++){
//     file->Init(slice,patch);
//     UInt_t ndigits=0;
//     UInt_t maxclusters=100000;
//     UInt_t pointsize = maxclusters*sizeof(AliHLTTPCSpacePointData);
//     AliHLTTPCSpacePointData *points = (AliHLTTPCSpacePointData*)memory->Allocate(pointsize);
//     AliHLTTPCDigitRowData *digits = (AliHLTTPCDigitRowData*)file->AliAltroDigits2Memory(ndigits,event);
//     AliHLTTPCClusterFinder *cf = new AliHLTTPCClusterFinder();
//     cf->SetMatchWidth(2);
//     cf->InitSlice( slice, patch, row[0], row[1], maxPoints );
//     cf->SetSTDOutput(kTRUE);    //Some output to standard IO
//     cf->SetRawSP(kFALSE);       //Convert space points to local system
//     cf->SetThreshold(5);        //Threshold of cluster charge
//     cf->SetDeconv(kTRUE);       //Deconv in pad and time direction
//     cf->SetCalcErr(kTRUE);      //Calculate the errors of the spacepoints
//     cf->SetOutputArray(points); //Move the spacepoints to the array
//     cf->Read(iter->fPtr, iter->fSize ); //give the data to the cf
//     cf->ProcessDigits();        //process the rows given by init
//     Int_t npoints = cf->GetNumberOfClusters();
//     AliHLTTPCMemHandler *out= new AliHLTTPCMemHandler();
//     out->SetBinaryOutput(fname);
//     out->Memory2Binary(npoints,points); //store the spacepoints
//     out->CloseBinaryOutput();
//     delete out;
//     file->free();
//     delete cf;
//   }
// }
*/ ClassImp(AliHLTTPCClusterFinder) AliHLTTPCClusterFinder::AliHLTTPCClusterFinder() { //constructor fMatch = 1; fThreshold = 10; fXYErr = 0.2; fZErr = 0.3; fDeconvPad = kTRUE; fDeconvTime = kTRUE; fStdout = kFALSE; fCalcerr = kTRUE; fRawSP = kFALSE; fFirstRow=0; fLastRow=0; fDigitReader = 0; } AliHLTTPCClusterFinder::~AliHLTTPCClusterFinder() { //destructor } void AliHLTTPCClusterFinder::InitSlice(Int_t slice,Int_t patch,Int_t firstrow, Int_t lastrow,Int_t nmaxpoints) { //init slice fNClusters = 0; fMaxNClusters = nmaxpoints; fCurrentSlice = slice; fCurrentPatch = patch; fFirstRow = firstrow; fLastRow = lastrow; } void AliHLTTPCClusterFinder::InitSlice(Int_t slice,Int_t patch,Int_t nmaxpoints) { //init slice fNClusters = 0; fMaxNClusters = nmaxpoints; fCurrentSlice = slice; fCurrentPatch = patch; fFirstRow=AliHLTTPCTransform::GetFirstRow(patch); fLastRow=AliHLTTPCTransform::GetLastRow(patch); } void AliHLTTPCClusterFinder::SetOutputArray(AliHLTTPCSpacePointData *pt) { //set pointer to output fSpacePointData = pt; } void AliHLTTPCClusterFinder::Read(void* ptr,unsigned long size){ //set input pointer fPtr = (UChar_t*)ptr; fSize = size; } void AliHLTTPCClusterFinder::ProcessDigits() { bool readValue = true; Int_t newRow = 0; Int_t rowOffset = 0; UChar_t pad; UShort_t time,newTime=0; UInt_t charge,newPad=0; fNClusters = 0; // initialize block for reading packed data fDigitReader->InitBlock(fPtr,fSize,fFirstRow,fLastRow); readValue = fDigitReader->Next(); if (!readValue)return; pad = fDigitReader->GetPad(); time = fDigitReader->GetTime(); fCurrentRow = fDigitReader->GetRow(); if ( fCurrentPatch >= 2 ) // Outer sector, patches 2, 3, 4, 5 rowOffset = AliHLTTPCTransform::GetFirstRow( 2 ); fCurrentRow += rowOffset; UInt_t lastpad = 123456789; AliClusterData *pad1[5000]; //2 lists for internal memory=2pads AliClusterData *pad2[5000]; //2 lists for internal memory=2pads AliClusterData clusterlist[10000]; //Clusterlist AliClusterData **currentPt; //List of pointers to the current pad AliClusterData **previousPt; //List of pointers to the previous pad currentPt = pad2; previousPt = pad1; UInt_t nprevious=0,ncurrent=0,ntotal=0; while ( readValue ){ // Reads through all digits in block if(pad != lastpad){ //This is a new pad //Switch the lists: if(currentPt == pad2){ currentPt = pad1; previousPt = pad2; } else { currentPt = pad2; previousPt = pad1; } nprevious = ncurrent; ncurrent = 0; if(pad != lastpad+1){ //this happens if there is a pad with no signal. nprevious = ncurrent = 0; } lastpad = pad; } Bool_t newcluster = kTRUE; UInt_t seqcharge=0,seqaverage=0,seqerror=0; UInt_t lastcharge=0,lastwas_falling=0; Int_t newbin=-1; if(fDeconvTime){ redo: //This is a goto. if(newbin > -1){ //bin = newbin; newbin = -1; } lastcharge=0; lastwas_falling = 0; } // LOOP OVER CURRENR SEQUENCE while(1){ //Loop over current charge = fDigitReader->GetSignal(); if(time >= AliHLTTPCTransform::GetNTimeBins()){ LOG(AliHLTTPCLog::kFatal,"AliHLTTPCClusterFinder::ProcessRow","Digits") <<"Timebin out of range "<<(Int_t)time< lastcharge){ if(lastwas_falling){ newbin = 1; break; } } else lastwas_falling = 1; //last pixel was larger than this lastcharge = charge; } //Sum the total charge of this sequence seqcharge += charge; seqaverage += time*charge; seqerror += time*time*charge; readValue = fDigitReader->Next(); //Check where to stop: if(!readValue) break; //No more value newPad = fDigitReader->GetPad(); newTime = fDigitReader->GetTime(); newRow = fDigitReader->GetRow() + rowOffset; if(newPad != pad)break; //new pad if(newTime != time+1) break; //end of sequence // pad = newpad; is equal time = newTime; }//end loop over sequence //Calculate mean of sequence: Int_t seqmean=0; if(seqcharge) seqmean = seqaverage/seqcharge; else{ LOG(AliHLTTPCLog::kFatal,"AliHLTTPCClusterFinder::ProcessRow","Data") <<"Error in data given to the cluster finder"<fLastMergedPad==pad) continue; Int_t difference = seqmean - previousPt[p]->fMean; if(difference < -fMatch) break; if(difference <= fMatch){ //There is a match here!! AliClusterData *local = previousPt[p]; if(fDeconvPad){ if(seqcharge > local->fLastCharge){ if(local->fChargeFalling){ //The previous pad was falling break; //create a new cluster } } else local->fChargeFalling = 1; local->fLastCharge = seqcharge; } //Don't create a new cluster, because we found a match newcluster = kFALSE; //Update cluster on current pad with the matching one: local->fTotalCharge += seqcharge; local->fPad += padmean; local->fPad2 += paderror; local->fTime += seqaverage; local->fTime2 += seqerror; local->fMean = seqmean; local->fFlags++; //means we have more than one pad local->fLastMergedPad = pad; currentPt[ncurrent] = local; ncurrent++; break; } //Checking for match at previous pad } //Loop over results on previous pad. if(newcluster){ //Start a new cluster. Add it to the clusterlist, and update //the list of pointers to clusters in current pad. //current pad will be previous pad on next pad. //Add to the clusterlist: AliClusterData *tmp = &clusterlist[ntotal]; tmp->fTotalCharge = seqcharge; tmp->fPad = padmean; tmp->fPad2 = paderror; tmp->fTime = seqaverage; tmp->fTime2 = seqerror; tmp->fMean = seqmean; tmp->fFlags = 0; //flags for single pad clusters tmp->fLastMergedPad = pad; if(fDeconvPad){ tmp->fChargeFalling = 0; tmp->fLastCharge = seqcharge; } //Update list of pointers to previous pad: currentPt[ncurrent] = &clusterlist[ntotal]; ntotal++; ncurrent++; } if(fDeconvTime) if(newbin >= 0) goto redo; // to prevent endless loop if(time >= AliHLTTPCTransform::GetNTimeBins()){ LOG(AliHLTTPCLog::kFatal,"AliHLTTPCClusterFinder::ProcessRow","Digits") <<"Timebin out of range "<<(Int_t)time<= fMaxNClusters) { LOG(AliHLTTPCLog::kError,"AliHLTTPCClustFinder::WriteClusters","Cluster Finder") <fRow < (UInt_t)fCurrentRow){ AliHLTTPCMemHandler::UpdateRowPointer(rowPt); continue; } AliHLTTPCDigitData *digPt = (AliHLTTPCDigitData*)rowPt->fDigitData; for(UInt_t j=0; jfNDigit; j++){ Int_t cpad = digPt[j].fPad; Int_t ctime = digPt[j].fTime; if(cpad != pad) continue; if(ctime != time) continue; trackID[0] = digPt[j].fTrackID[0]; trackID[1] = digPt[j].fTrackID[1]; trackID[2] = digPt[j].fTrackID[2]; //cout<<"Reading row "<