2 // Original: AliHLTClustFinderNew.cxx,v 1.29 2005/06/14 10:55:21 cvetan Exp
4 /**************************************************************************
5 * This file is property of and copyright by the ALICE HLT Project *
6 * ALICE Experiment at CERN, All rights reserved. *
8 * Primary Authors: Anders Vestbo, Constantin Loizides, Jochen Thaeder *
9 * Kenneth Aamodt <kenneth.aamodt@student.uib.no> *
10 * for The ALICE HLT Project. *
12 * Permission to use, copy, modify and distribute this software and its *
13 * documentation strictly for non-commercial purposes is hereby granted *
14 * without fee, provided that the above copyright notice appears in all *
15 * copies and that both the copyright notice and this permission notice *
16 * appear in the supporting documentation. The authors make no claims *
17 * about the suitability of this software for any purpose. It is *
18 * provided "as is" without express or implied warranty. *
19 **************************************************************************/
21 /** @file AliHLTTPCClusterFinder.cxx
22 @author Anders Vestbo, Constantin Loizides, Jochen Thaeder
23 Kenneth Aamodt kenneth.aamodt@student.uib.no
25 @brief Cluster Finder for the TPC
28 #include "AliHLTTPCDigitReader.h"
29 #include "AliHLTTPCRootTypes.h"
30 #include "AliHLTTPCLogging.h"
31 #include "AliHLTTPCClusterFinder.h"
32 #include "AliHLTTPCDigitData.h"
33 #include "AliHLTTPCTransform.h"
34 #include "AliHLTTPCSpacePointData.h"
35 #include "AliHLTTPCMemHandler.h"
36 #include "AliHLTTPCPad.h"
37 #include "AliHLTTPCPadArray.h"
43 /** \class AliHLTTPCClusterFinder
45 // The current cluster finder for HLT
48 //Basically we have two versions for the cluster finder now.
49 //The default version, reads the data pad by pad, and find the
50 //clusters as it reads the data. The other version has now been
51 //developed to cope with unsorted data. New methods for the unsorted
52 //version can be found at the end of the default one i the source file.
53 //Currently the new version is only build to manage zero-suppressed data.
54 //More functionality will be added later.
56 // The cluster finder is initialized with the Init function,
57 // providing the slice and patch information to work on.
59 // The input is a provided by the AliHLTTPCDigitReader class,
60 // using the init() funktion, and the next() funktion in order
61 // to get the next bin. Either packed or unpacked data can be
62 // processed, dependent if one uses AliHLTTPCDigitReaderPacked
63 // class or AliHLTTPCDigitReaderUnpacked class in the
64 // Clusterfinder Component.
65 // The resulting space points will be in the
66 // array given by the SetOutputArray function.
68 // There are several setters which control the behaviour:
70 // - SetXYError(Float_t): set fixed error in XY direction
71 // - SetZError(Float_t): set fixed error in Z direction
72 // (used if errors are not calculated)
73 // - SetDeconv(Bool_t): switch on/off deconvolution
74 // - SetThreshold(UInt_t): set charge threshold for cluster
75 // - SetMatchWidth(UInt_t): set the match distance in
76 // time for sequences to be merged
77 // - SetSTDOutput(Bool_t): switch on/off output about found clusters
78 // - SetCalcErr(Bool_t): switch on/off calculation of
79 // space point errors (or widths in raw system)
80 // - SetRawSP(Bool_t): switch on/off convertion to raw system
85 // AliHLTTPCFileHandler *file = new AliHLTTPCFileHandler();
86 // file->SetAliInput(digitfile); //give some input file
87 // for(int slice=0; slice<=35; slice++){
88 // for(int patch=0; pat<6; pat++){
89 // file->Init(slice,patch);
91 // UInt_t maxclusters=100000;
92 // UInt_t pointsize = maxclusters*sizeof(AliHLTTPCSpacePointData);
93 // AliHLTTPCSpacePointData *points = (AliHLTTPCSpacePointData*)memory->Allocate(pointsize);
94 // AliHLTTPCDigitRowData *digits = (AliHLTTPCDigitRowData*)file->AliAltroDigits2Memory(ndigits,event);
95 // AliHLTTPCClusterFinder *cf = new AliHLTTPCClusterFinder();
96 // cf->SetMatchWidth(2);
97 // cf->InitSlice( slice, patch, row[0], row[1], maxPoints );
98 // cf->SetSTDOutput(kTRUE); //Some output to standard IO
99 // cf->SetRawSP(kFALSE); //Convert space points to local system
100 // cf->SetThreshold(5); //Threshold of cluster charge
101 // cf->SetDeconv(kTRUE); //Deconv in pad and time direction
102 // cf->SetCalcErr(kTRUE); //Calculate the errors of the spacepoints
103 // cf->SetOutputArray(points); //Move the spacepoints to the array
104 // cf->Read(iter->fPtr, iter->fSize ); //give the data to the cf
105 // cf->ProcessDigits(); //process the rows given by init
106 // Int_t npoints = cf->GetNumberOfClusters();
107 // AliHLTTPCMemHandler *out= new AliHLTTPCMemHandler();
108 // out->SetBinaryOutput(fname);
109 // out->Memory2Binary(npoints,points); //store the spacepoints
110 // out->CloseBinaryOutput();
118 ClassImp(AliHLTTPCClusterFinder)
120 AliHLTTPCClusterFinder::AliHLTTPCClusterFinder()
122 fSpacePointData(NULL),
138 fSignalThreshold(-1),
143 fOccupancyLimit(1.0),
149 AliHLTTPCClusterFinder::AliHLTTPCClusterFinder(const AliHLTTPCClusterFinder& src)
151 fSpacePointData(NULL),
152 fDigitReader(src.fDigitReader),
155 fDeconvTime(src.fDeconvTime),
156 fDeconvPad(src.fDeconvPad),
157 fStdout(src.fStdout),
158 fCalcerr(src.fCalcerr),
160 fFirstRow(src.fFirstRow),
161 fLastRow(src.fLastRow),
162 fCurrentRow(src.fCurrentRow),
163 fCurrentSlice(src.fCurrentSlice),
164 fCurrentPatch(src.fCurrentPatch),
166 fThreshold(src.fThreshold),
167 fSignalThreshold(src.fSignalThreshold),
168 fNClusters(src.fNClusters),
169 fMaxNClusters(src.fMaxNClusters),
172 fOccupancyLimit(src.fOccupancyLimit),
177 AliHLTTPCClusterFinder& AliHLTTPCClusterFinder::operator=(const AliHLTTPCClusterFinder& src)
180 fThreshold=src.fThreshold;
181 fSignalThreshold=src.fSignalThreshold;
182 fOccupancyLimit=src.fOccupancyLimit;
185 fDeconvPad=src.fDeconvPad;
186 fDeconvTime=src.fDeconvTime;
188 fCalcerr=src.fCalcerr;
190 fFirstRow=src.fFirstRow;
191 fLastRow=src.fLastRow;
192 fDigitReader=src.fDigitReader;
196 AliHLTTPCClusterFinder::~AliHLTTPCClusterFinder()
201 void AliHLTTPCClusterFinder::InitSlice(Int_t slice,Int_t patch,Int_t firstrow, Int_t lastrow,Int_t nmaxpoints)
205 fMaxNClusters = nmaxpoints;
206 fCurrentSlice = slice;
207 fCurrentPatch = patch;
208 fFirstRow = firstrow;
212 void AliHLTTPCClusterFinder::InitSlice(Int_t slice,Int_t patch,Int_t nmaxpoints)
216 fMaxNClusters = nmaxpoints;
217 fCurrentSlice = slice;
218 fCurrentPatch = patch;
219 fFirstRow=AliHLTTPCTransform::GetFirstRow(patch);
220 fLastRow=AliHLTTPCTransform::GetLastRow(patch);
223 void AliHLTTPCClusterFinder::SetOutputArray(AliHLTTPCSpacePointData *pt)
225 //set pointer to output
226 fSpacePointData = pt;
229 void AliHLTTPCClusterFinder::Read(void* ptr,unsigned long size){
231 fPtr = (UChar_t*)ptr;
235 void AliHLTTPCClusterFinder::ProcessDigits()
237 bool readValue = true;
240 UShort_t time=0,newTime=0;
241 UInt_t pad=0,newPad=0;
242 AliHLTTPCSignal_t charge=0;
246 // initialize block for reading packed data
247 fDigitReader->InitBlock(fPtr,fSize,fFirstRow,fLastRow,fCurrentPatch,fCurrentSlice);
248 readValue = fDigitReader->Next();
250 // Matthias 08.11.2006 the following return would cause termination without writing the
251 // ClusterData and thus would block the component. I just want to have the commented line
252 // here for information
253 //if (!readValue)return;
255 pad = fDigitReader->GetPad();
256 time = fDigitReader->GetTime();
257 fCurrentRow = fDigitReader->GetRow();
259 if ( fCurrentPatch >= 2 ) // Outer sector, patches 2, 3, 4, 5
260 rowOffset = AliHLTTPCTransform::GetFirstRow( 2 );
262 fCurrentRow += rowOffset;
264 UInt_t lastpad = 123456789;
265 const UInt_t kPadArraySize=5000;
266 const UInt_t kClusterListSize=10000;
267 AliClusterData *pad1[kPadArraySize]; //2 lists for internal memory=2pads
268 AliClusterData *pad2[kPadArraySize]; //2 lists for internal memory=2pads
269 AliClusterData clusterlist[kClusterListSize]; //Clusterlist
271 AliClusterData **currentPt; //List of pointers to the current pad
272 AliClusterData **previousPt; //List of pointers to the previous pad
275 UInt_t nprevious=0,ncurrent=0,ntotal=0;
277 /* quick implementation of baseline calculation and zero suppression
278 open a pad object for each pad and delete it after processing.
279 later a list of pad objects with base line history can be used
280 The whole thing only works if we really get unprocessed raw data, if
281 the data is already zero suppressed, there might be gaps in the time
284 Int_t gatingGridOffset=50;
285 AliHLTTPCPad baseline(gatingGridOffset, AliHLTTPCTransform::GetNTimeBins());
286 // just to make later conversion to a list of objects easier
287 AliHLTTPCPad* pCurrentPad=NULL;
288 if (fSignalThreshold>=0) {
289 pCurrentPad=&baseline;
290 baseline.SetThreshold(fSignalThreshold);
293 while ( readValue ){ // Reads through all digits in block
299 if(currentPt == pad2){
307 nprevious = ncurrent;
309 if(pad != lastpad+1){
310 //this happens if there is a pad with no signal.
311 nprevious = ncurrent = 0;
316 Bool_t newcluster = kTRUE;
317 UInt_t seqcharge=0,seqaverage=0,seqerror=0;
318 AliHLTTPCSignal_t lastcharge=0;
319 UInt_t bLastWasFalling=0;
324 redo: //This is a goto.
335 while(1){ //Loop over time bins of current pad
336 // read all the values for one pad at once to calculate the base line
338 if (!pCurrentPad->IsStarted()) {
339 //HLTDebug("reading data for pad %d, padrow %d", fDigitReader->GetPad(), fDigitReader->GetRow()+rowOffset);
340 pCurrentPad->SetID(fDigitReader->GetRow()+rowOffset,fDigitReader->GetPad());
341 if ((pCurrentPad->StartEvent())>=0) {
343 if ((fDigitReader->GetRow()+rowOffset)!=pCurrentPad->GetRowNumber()) break;
344 if (fDigitReader->GetPad()!=pCurrentPad->GetPadNumber()) break;
345 pCurrentPad->SetRawData(fDigitReader->GetTime(), fDigitReader->GetSignal());
346 //HLTDebug("set raw data to pad: bin %d charge %d", fDigitReader->GetTime(), fDigitReader->GetSignal());
347 } while ((readValue = fDigitReader->Next())!=0);
349 pCurrentPad->CalculateBaseLine(AliHLTTPCTransform::GetNTimeBins()/2);
350 if (pCurrentPad->Next(kTRUE/*do zero suppression*/)==0) {
351 //HLTDebug("no data available after zero suppression");
352 pCurrentPad->StopEvent();
353 pCurrentPad->ResetHistory();
356 time=pCurrentPad->GetCurrentPosition();
357 if (time>pCurrentPad->GetSize()) {
358 HLTError("invalid time bin for pad");
365 Float_t occupancy=pCurrentPad->GetOccupancy();
366 //HLTDebug("pad %d occupancy level: %f", pCurrentPad->GetPadNumber(), occupancy);
367 if ( occupancy < fOccupancyLimit ) {
368 charge = pCurrentPad->GetCorrectedData();
371 //HLTDebug("ignoring pad %d with occupancy level %f", pCurrentPad->GetPadNumber(), occupancy);
374 charge = fDigitReader->GetSignal();
376 //HLTDebug("get next charge value: position %d charge %d", time, charge);
380 if (fDigitReader->GetRow() == 90){
381 ///// LOG(AliHLTTPCLog::kFatal,"AliHLTTPCClusterFinder::Row","row90") << "PAD=" << fDigitReader->GetPad() << " TIME=" << fDigitReader->GetTime()
382 // << " SIGNAL=" << fDigitReader->GetSignal() << ENDLOG;
386 if(time >= AliHLTTPCTransform::GetNTimeBins()){
387 HLTWarning("Timebin (%d) out of range (%d)", time, AliHLTTPCTransform::GetNTimeBins());
392 //Get the current ADC-value
395 //Check if the last pixel in the sequence is smaller than this
396 if(charge > lastcharge){
402 else bLastWasFalling = 1; //last pixel was larger than this
406 //Sum the total charge of this sequence
408 seqaverage += time*charge;
409 seqerror += time*time*charge;
413 if((pCurrentPad->Next(kTRUE/*do zero suppression*/))==0) {
414 pCurrentPad->StopEvent();
415 pCurrentPad->ResetHistory();
417 newPad = fDigitReader->GetPad();
418 newTime = fDigitReader->GetTime();
419 newRow = fDigitReader->GetRow() + rowOffset;
424 newPad=pCurrentPad->GetPadNumber();
425 newTime=pCurrentPad->GetCurrentPosition();
426 newRow=pCurrentPad->GetRowNumber();
428 readValue = fDigitReader->Next();
429 //Check where to stop:
430 if(!readValue) break; //No more value
432 newPad = fDigitReader->GetPad();
433 newTime = fDigitReader->GetTime();
434 newRow = fDigitReader->GetRow() + rowOffset;
437 if(newPad != pad)break; //new pad
438 if(newTime != time+1) break; //end of sequence
440 // pad = newpad; is equal
443 }//end loop over sequence
445 //HLTDebug("ended time bin sequence loop: seqcharge=%d readValue=%d", seqcharge, readValue);
446 //HLTDebug("pad=%d newpad=%d current row=%d newrow=%d", pad, newPad, fCurrentRow, newRow);
448 // with active zero suppression zero values are possible
452 //Calculate mean of sequence:
455 seqmean = seqaverage/seqcharge;
457 LOG(AliHLTTPCLog::kFatal,"AliHLTTPCClusterFinder::ProcessRow","Data")
458 <<"Error in data given to the cluster finder"<<ENDLOG;
463 //Calculate mean in pad direction:
464 Int_t padmean = seqcharge*pad;
465 Int_t paderror = pad*padmean;
467 //Compare with results on previous pad:
468 for(UInt_t p=0; p<nprevious && p<kPadArraySize && ncurrent<kPadArraySize; p++){
470 //dont merge sequences on the same pad twice
471 if(previousPt[p]->fLastMergedPad==pad) continue;
473 Int_t difference = seqmean - previousPt[p]->fMean;
474 if(difference < -fMatch) break;
476 if(difference <= fMatch){ //There is a match here!!
477 AliClusterData *local = previousPt[p];
480 if(seqcharge > local->fLastCharge){
481 if(local->fChargeFalling){ //The previous pad was falling
482 break; //create a new cluster
485 else local->fChargeFalling = 1;
486 local->fLastCharge = seqcharge;
489 //Don't create a new cluster, because we found a match
492 //Update cluster on current pad with the matching one:
493 local->fTotalCharge += seqcharge;
494 local->fPad += padmean;
495 local->fPad2 += paderror;
496 local->fTime += seqaverage;
497 local->fTime2 += seqerror;
498 local->fMean = seqmean;
499 local->fFlags++; //means we have more than one pad
500 local->fLastMergedPad = pad;
502 currentPt[ncurrent] = local;
506 } //Checking for match at previous pad
507 } //Loop over results on previous pad.
509 if(newcluster && ncurrent<kPadArraySize){
510 //Start a new cluster. Add it to the clusterlist, and update
511 //the list of pointers to clusters in current pad.
512 //current pad will be previous pad on next pad.
514 //Add to the clusterlist:
515 AliClusterData *tmp = &clusterlist[ntotal];
516 tmp->fTotalCharge = seqcharge;
518 tmp->fPad2 = paderror;
519 tmp->fTime = seqaverage;
520 tmp->fTime2 = seqerror;
521 tmp->fMean = seqmean;
522 tmp->fFlags = 0; //flags for single pad clusters
523 tmp->fLastMergedPad = pad;
526 tmp->fChargeFalling = 0;
527 tmp->fLastCharge = seqcharge;
530 //Update list of pointers to previous pad:
531 currentPt[ncurrent] = &clusterlist[ntotal];
537 if(newbin >= 0) goto redo;
539 // to prevent endless loop
540 if(time >= AliHLTTPCTransform::GetNTimeBins()){
541 HLTWarning("Timebin (%d) out of range (%d)", time, AliHLTTPCTransform::GetNTimeBins());
546 if(!readValue) break; //No more value
548 if (ntotal>=kClusterListSize || ncurrent>=kPadArraySize) {
549 HLTWarning("pad array size exceeded ntotal=%d ncurrent=%d, skip rest of the data", ntotal, ncurrent);
553 if(fCurrentRow != newRow){
554 WriteClusters(ntotal,clusterlist);
564 fCurrentRow = newRow;
570 } // END while(readValue)
572 WriteClusters(ntotal,clusterlist);
574 HLTInfo("ClusterFinder found %d clusters in slice %d patch %d", fNClusters, fCurrentSlice, fCurrentPatch);
578 void AliHLTTPCClusterFinder::WriteClusters(Int_t nclusters,AliClusterData *list)
580 //write cluster to output pointer
581 Int_t thisrow,thissector;
582 UInt_t counter = fNClusters;
584 for(int j=0; j<nclusters; j++)
589 if(!list[j].fFlags) continue; //discard single pad clusters
590 if(list[j].fTotalCharge < fThreshold) continue; //noise cluster
593 Float_t fpad =(Float_t)list[j].fPad / list[j].fTotalCharge;
594 Float_t fpad2=fXYErr*fXYErr; //fixed given error
595 Float_t ftime =(Float_t)list[j].fTime / list[j].fTotalCharge;
596 Float_t ftime2=fZErr*fZErr; //fixed given error
600 fCurrentRow=list[j].fRow;
603 if(fCalcerr) { //calc the errors, otherwice take the fixed error
604 Int_t patch = AliHLTTPCTransform::GetPatch(fCurrentRow);
605 UInt_t q2=list[j].fTotalCharge*list[j].fTotalCharge;
606 Float_t sy2=list[j].fPad2 * list[j].fTotalCharge - list[j].fPad * list[j].fPad;
609 LOG(AliHLTTPCLog::kError,"AliHLTTPCClusterFinder::WriteClusters","Cluster width")
610 <<"SigmaY2 negative "<<sy2<<" on row "<<fCurrentRow<<" "<<fpad<<" "<<ftime<<ENDLOG;
614 fpad2 = (sy2 + 1./12)*AliHLTTPCTransform::GetPadPitchWidth(patch)*AliHLTTPCTransform::GetPadPitchWidth(patch);
616 fpad2*=0.108; //constants are from offline studies
620 } else fpad2=sy2; //take the width not the error
622 Float_t sz2=list[j].fTime2*list[j].fTotalCharge - list[j].fTime*list[j].fTime;
625 LOG(AliHLTTPCLog::kError,"AliHLTTPCClusterFinder::WriteClusters","Cluster width")
626 <<"SigmaZ2 negative "<<sz2<<" on row "<<fCurrentRow<<" "<<fpad<<" "<<ftime<<ENDLOG;
630 ftime2 = (sz2 + 1./12)*AliHLTTPCTransform::GetZWidth()*AliHLTTPCTransform::GetZWidth();
632 ftime2 *= 0.169; //constants are from offline studies
636 } else ftime2=sz2; //take the width, not the error
640 cout<<"WriteCluster: padrow "<<fCurrentRow<<" pad "<<fpad << " +- "<<fpad2<<" time "<<ftime<<" +- "<<ftime2<<" charge "<<list[j].fTotalCharge<<endl;
643 AliHLTTPCTransform::Slice2Sector(fCurrentSlice,fCurrentRow,thissector,thisrow);
644 AliHLTTPCTransform::Raw2Local(xyz,thissector,thisrow,fpad,ftime);
646 if(xyz[0]==0) LOG(AliHLTTPCLog::kError,"AliHLTTPCClustFinder","Cluster Finder")
647 <<AliHLTTPCLog::kDec<<"Zero cluster"<<ENDLOG;
648 if(fNClusters >= fMaxNClusters)
650 LOG(AliHLTTPCLog::kError,"AliHLTTPCClustFinder::WriteClusters","Cluster Finder")
651 <<AliHLTTPCLog::kDec<<"Too many clusters "<<fNClusters<<ENDLOG;
655 fSpacePointData[counter].fX = xyz[0];
656 fSpacePointData[counter].fY = xyz[1];
657 fSpacePointData[counter].fZ = xyz[2];
660 fSpacePointData[counter].fX = fCurrentRow;
661 fSpacePointData[counter].fY = fpad;
662 fSpacePointData[counter].fZ = ftime;
665 fSpacePointData[counter].fCharge = list[j].fTotalCharge;
666 fSpacePointData[counter].fPadRow = fCurrentRow;
667 fSpacePointData[counter].fSigmaY2 = fpad2;
668 fSpacePointData[counter].fSigmaZ2 = ftime2;
670 fSpacePointData[counter].fUsed = kFALSE; // only used / set in AliHLTTPCDisplay
671 fSpacePointData[counter].fTrackN = -1; // only used / set in AliHLTTPCDisplay
673 Int_t patch=fCurrentPatch;
674 if(patch==-1) patch=0; //never store negative patch number
675 fSpacePointData[counter].fID = counter
676 +((fCurrentSlice&0x7f)<<25)+((patch&0x7)<<22);//Uli
680 GetTrackID((Int_t)rint(fpad),(Int_t)rint(ftime),trackID);
682 fSpacePointData[counter].fTrackID[0] = trackID[0];
683 fSpacePointData[counter].fTrackID[1] = trackID[1];
684 fSpacePointData[counter].fTrackID[2] = trackID[2];
686 //cout<<"padrow "<<fCurrentRow<<" pad "<<(Int_t)rint(fpad)<<" time "<<(Int_t)rint(ftime)<<" Trackid "<<trackID[0]<<endl;
694 // STILL TO FIX ----------------------------------------------------------------------------
697 void AliHLTTPCClusterFinder::GetTrackID(Int_t pad,Int_t time,Int_t *trackID)
700 AliHLTTPCDigitRowData *rowPt = (AliHLTTPCDigitRowData*)fDigitRowData;
702 trackID[0]=trackID[1]=trackID[2]=-2;
703 //cout<<"Looking for pad "<<pad<<" time "<<time<<endl;
704 for(Int_t i=fFirstRow; i<=fLastRow; i++){
705 if(rowPt->fRow < (UInt_t)fCurrentRow){
706 AliHLTTPCMemHandler::UpdateRowPointer(rowPt);
709 AliHLTTPCDigitData *digPt = (AliHLTTPCDigitData*)rowPt->fDigitData;
710 for(UInt_t j=0; j<rowPt->fNDigit; j++){
711 Int_t cpad = digPt[j].fPad;
712 Int_t ctime = digPt[j].fTime;
713 if(cpad != pad) continue;
714 if(ctime != time) continue;
716 trackID[0] = digPt[j].fTrackID[0];
717 trackID[1] = digPt[j].fTrackID[1];
718 trackID[2] = digPt[j].fTrackID[2];
720 //cout<<"Reading row "<<fCurrentRow<<" pad "<<cpad<<" time "<<ctime<<" trackID "<<digPt[j].fTrackID[0]<<endl;
728 //----------------------------------Methods for the new unsorted way of reading the data --------------------------------
730 void AliHLTTPCClusterFinder::SetPadArray(AliHLTTPCPadArray * padArray){
734 void AliHLTTPCClusterFinder::ReadDataUnsorted(void* ptr,unsigned long size){
736 fPtr = (UChar_t*)ptr;
739 fDigitReader->InitBlock(fPtr,fSize,fFirstRow,fLastRow,fCurrentPatch,fCurrentSlice);
741 fPadArray->SetDigitReader(fDigitReader);
742 fPadArray->ReadData();
744 void AliHLTTPCClusterFinder::FindClusters(){
745 fPadArray->FindClusterCandidates();
746 fPadArray->FindClusters(fMatch);
748 AliClusterData * clusterlist = new AliClusterData[fPadArray->fClusters.size()]; //Clusterlist
749 for(int i=0;i<fPadArray->fClusters.size();i++){
750 clusterlist[i].fTotalCharge = fPadArray->fClusters[i].fTotalCharge;
751 clusterlist[i].fPad = fPadArray->fClusters[i].fPad;
752 clusterlist[i].fPad2 = fPadArray->fClusters[i].fPad2;
753 clusterlist[i].fTime = fPadArray->fClusters[i].fTime;
754 clusterlist[i].fTime2 = fPadArray->fClusters[i].fTime2;
755 clusterlist[i].fMean = fPadArray->fClusters[i].fMean;
756 clusterlist[i].fFlags = fPadArray->fClusters[i].fFlags;
757 clusterlist[i].fChargeFalling = fPadArray->fClusters[i].fChargeFalling;
758 clusterlist[i].fLastCharge = fPadArray->fClusters[i].fLastCharge;
759 clusterlist[i].fLastMergedPad = fPadArray->fClusters[i].fLastMergedPad;
760 clusterlist[i].fRow = fPadArray->fClusters[i].fRowNumber;
762 WriteClusters(fPadArray->fClusters.size(),clusterlist);
763 delete [] clusterlist;
765 void AliHLTTPCClusterFinder::WriteClusters(Int_t nclusters,AliHLTTPCClusters *list)//This is used when using the AliHLTTPCClusters class for cluster data
767 //write cluster to output pointer
768 Int_t thisrow,thissector;
769 UInt_t counter = fNClusters;
771 for(int j=0; j<nclusters; j++)
773 if(!list[j].fFlags) continue; //discard single pad clusters
774 if(list[j].fTotalCharge < fThreshold) continue; //noise cluster
777 Float_t fpad =(Float_t)list[j].fPad / list[j].fTotalCharge;
778 Float_t fpad2=fXYErr*fXYErr; //fixed given error
779 Float_t ftime =(Float_t)list[j].fTime / list[j].fTotalCharge;
780 Float_t ftime2=fZErr*fZErr; //fixed given error
783 if(fCalcerr) { //calc the errors, otherwice take the fixed error
784 Int_t patch = AliHLTTPCTransform::GetPatch(fCurrentRow);
785 UInt_t q2=list[j].fTotalCharge*list[j].fTotalCharge;
786 Float_t sy2=list[j].fPad2 * list[j].fTotalCharge - list[j].fPad * list[j].fPad;
789 LOG(AliHLTTPCLog::kError,"AliHLTTPCClusterFinder::WriteClusters","Cluster width")
790 <<"SigmaY2 negative "<<sy2<<" on row "<<fCurrentRow<<" "<<fpad<<" "<<ftime<<ENDLOG;
794 fpad2 = (sy2 + 1./12)*AliHLTTPCTransform::GetPadPitchWidth(patch)*AliHLTTPCTransform::GetPadPitchWidth(patch);
796 fpad2*=0.108; //constants are from offline studies
800 } else fpad2=sy2; //take the width not the error
802 Float_t sz2=list[j].fTime2*list[j].fTotalCharge - list[j].fTime*list[j].fTime;
805 LOG(AliHLTTPCLog::kError,"AliHLTTPCClusterFinder::WriteClusters","Cluster width")
806 <<"SigmaZ2 negative "<<sz2<<" on row "<<fCurrentRow<<" "<<fpad<<" "<<ftime<<ENDLOG;
810 ftime2 = (sz2 + 1./12)*AliHLTTPCTransform::GetZWidth()*AliHLTTPCTransform::GetZWidth();
812 ftime2 *= 0.169; //constants are from offline studies
816 } else ftime2=sz2; //take the width, not the error
820 cout<<"WriteCluster: padrow "<<fCurrentRow<<" pad "<<fpad << " +- "<<fpad2<<" time "<<ftime<<" +- "<<ftime2<<" charge "<<list[j].fTotalCharge<<endl;
823 AliHLTTPCTransform::Slice2Sector(fCurrentSlice,fCurrentRow,thissector,thisrow);
824 AliHLTTPCTransform::Raw2Local(xyz,thissector,thisrow,fpad,ftime);
826 if(xyz[0]==0) LOG(AliHLTTPCLog::kError,"AliHLTTPCClustFinder","Cluster Finder")
827 <<AliHLTTPCLog::kDec<<"Zero cluster"<<ENDLOG;
828 if(fNClusters >= fMaxNClusters)
830 LOG(AliHLTTPCLog::kError,"AliHLTTPCClustFinder::WriteClusters","Cluster Finder")
831 <<AliHLTTPCLog::kDec<<"Too many clusters "<<fNClusters<<ENDLOG;
835 fSpacePointData[counter].fX = xyz[0];
836 fSpacePointData[counter].fY = xyz[1];
837 fSpacePointData[counter].fZ = xyz[2];
840 fSpacePointData[counter].fX = fCurrentRow;
841 fSpacePointData[counter].fY = fpad;
842 fSpacePointData[counter].fZ = ftime;
845 fSpacePointData[counter].fCharge = list[j].fTotalCharge;
846 fSpacePointData[counter].fPadRow = fCurrentRow;
847 fSpacePointData[counter].fSigmaY2 = fpad2;
848 fSpacePointData[counter].fSigmaZ2 = ftime2;
850 fSpacePointData[counter].fUsed = kFALSE; // only used / set in AliHLTTPCDisplay
851 fSpacePointData[counter].fTrackN = -1; // only used / set in AliHLTTPCDisplay
853 Int_t patch=fCurrentPatch;
854 if(patch==-1) patch=0; //never store negative patch number
855 fSpacePointData[counter].fID = counter
856 +((fCurrentSlice&0x7f)<<25)+((patch&0x7)<<22);//Uli
860 GetTrackID((Int_t)rint(fpad),(Int_t)rint(ftime),trackID);
862 fSpacePointData[counter].fTrackID[0] = trackID[0];
863 fSpacePointData[counter].fTrackID[1] = trackID[1];
864 fSpacePointData[counter].fTrackID[2] = trackID[2];
866 //cout<<"padrow "<<fCurrentRow<<" pad "<<(Int_t)rint(fpad)<<" time "<<(Int_t)rint(ftime)<<" Trackid "<<trackID[0]<<endl;