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()
238 bool readValue = true;
241 UShort_t time=0,newTime=0;
242 UInt_t pad=0,newPad=0;
243 AliHLTTPCSignal_t charge=0;
247 // initialize block for reading packed data
248 fDigitReader->InitBlock(fPtr,fSize,fFirstRow,fLastRow,fCurrentPatch,fCurrentSlice);
249 readValue = fDigitReader->Next();
251 // Matthias 08.11.2006 the following return would cause termination without writing the
252 // ClusterData and thus would block the component. I just want to have the commented line
253 // here for information
254 //if (!readValue)return;
256 pad = fDigitReader->GetPad();
257 time = fDigitReader->GetTime();
258 fCurrentRow = fDigitReader->GetRow();
260 if ( fCurrentPatch >= 2 ) // Outer sector, patches 2, 3, 4, 5
261 rowOffset = AliHLTTPCTransform::GetFirstRow( 2 );
263 fCurrentRow += rowOffset;
265 UInt_t lastpad = 123456789;
266 const UInt_t kPadArraySize=5000;
267 const UInt_t kClusterListSize=10000;
268 AliClusterData *pad1[kPadArraySize]; //2 lists for internal memory=2pads
269 AliClusterData *pad2[kPadArraySize]; //2 lists for internal memory=2pads
270 AliClusterData clusterlist[kClusterListSize]; //Clusterlist
272 AliClusterData **currentPt; //List of pointers to the current pad
273 AliClusterData **previousPt; //List of pointers to the previous pad
276 UInt_t nprevious=0,ncurrent=0,ntotal=0;
278 /* quick implementation of baseline calculation and zero suppression
279 open a pad object for each pad and delete it after processing.
280 later a list of pad objects with base line history can be used
281 The whole thing only works if we really get unprocessed raw data, if
282 the data is already zero suppressed, there might be gaps in the time
285 Int_t gatingGridOffset=50;
286 AliHLTTPCPad baseline(gatingGridOffset, AliHLTTPCTransform::GetNTimeBins());
287 // just to make later conversion to a list of objects easier
288 AliHLTTPCPad* pCurrentPad=NULL;
289 if (fSignalThreshold>=0) {
290 pCurrentPad=&baseline;
291 baseline.SetThreshold(fSignalThreshold);
294 while ( readValue!=0 && iResult>=0){ // Reads through all digits in block
301 if(currentPt == pad2){
309 nprevious = ncurrent;
311 if(pad != lastpad+1){
312 //this happens if there is a pad with no signal.
313 nprevious = ncurrent = 0;
318 Bool_t newcluster = kTRUE;
319 UInt_t seqcharge=0,seqaverage=0,seqerror=0;
320 AliHLTTPCSignal_t lastcharge=0;
321 UInt_t bLastWasFalling=0;
326 redo: //This is a goto.
337 while(iResult>=0){ //Loop over time bins of current pad
338 // read all the values for one pad at once to calculate the base line
340 if (!pCurrentPad->IsStarted()) {
341 //HLTDebug("reading data for pad %d, padrow %d", fDigitReader->GetPad(), fDigitReader->GetRow()+rowOffset);
342 pCurrentPad->SetID(fDigitReader->GetRow()+rowOffset,fDigitReader->GetPad());
343 if ((pCurrentPad->StartEvent())>=0) {
345 if ((fDigitReader->GetRow()+rowOffset)!=pCurrentPad->GetRowNumber()) break;
346 if (fDigitReader->GetPad()!=pCurrentPad->GetPadNumber()) break;
347 pCurrentPad->SetRawData(fDigitReader->GetTime(), fDigitReader->GetSignal());
348 //HLTDebug("set raw data to pad: bin %d charge %d", fDigitReader->GetTime(), fDigitReader->GetSignal());
349 } while ((readValue = fDigitReader->Next())!=0);
351 pCurrentPad->CalculateBaseLine(AliHLTTPCTransform::GetNTimeBins()/2);
352 if (pCurrentPad->Next(kTRUE/*do zero suppression*/)==0) {
353 //HLTDebug("no data available after zero suppression");
354 pCurrentPad->StopEvent();
355 pCurrentPad->ResetHistory();
358 time=pCurrentPad->GetCurrentPosition();
359 if (time>pCurrentPad->GetSize()) {
360 HLTError("invalid time bin for pad");
367 Float_t occupancy=pCurrentPad->GetOccupancy();
368 //HLTDebug("pad %d occupancy level: %f", pCurrentPad->GetPadNumber(), occupancy);
369 if ( occupancy < fOccupancyLimit ) {
370 charge = pCurrentPad->GetCorrectedData();
373 //HLTDebug("ignoring pad %d with occupancy level %f", pCurrentPad->GetPadNumber(), occupancy);
376 charge = fDigitReader->GetSignal();
378 //HLTDebug("get next charge value: position %d charge %d", time, charge);
382 if (fDigitReader->GetRow() == 90){
383 ///// LOG(AliHLTTPCLog::kFatal,"AliHLTTPCClusterFinder::Row","row90") << "PAD=" << fDigitReader->GetPad() << " TIME=" << fDigitReader->GetTime()
384 // << " SIGNAL=" << fDigitReader->GetSignal() << ENDLOG;
388 if(time >= AliHLTTPCTransform::GetNTimeBins()){
389 HLTWarning("Pad %d: Timebin (%d) out of range (%d)", pad, time, AliHLTTPCTransform::GetNTimeBins());
394 //Get the current ADC-value
397 //Check if the last pixel in the sequence is smaller than this
398 if(charge > lastcharge){
404 else bLastWasFalling = 1; //last pixel was larger than this
408 //Sum the total charge of this sequence
410 seqaverage += time*charge;
411 seqerror += time*time*charge;
415 if((pCurrentPad->Next(kTRUE/*do zero suppression*/))==0) {
416 pCurrentPad->StopEvent();
417 pCurrentPad->ResetHistory();
419 newPad = fDigitReader->GetPad();
420 newTime = fDigitReader->GetTime();
421 newRow = fDigitReader->GetRow() + rowOffset;
426 newPad=pCurrentPad->GetPadNumber();
427 newTime=pCurrentPad->GetCurrentPosition();
428 newRow=pCurrentPad->GetRowNumber();
430 readValue = fDigitReader->Next();
431 //Check where to stop:
432 if(!readValue) break; //No more value
434 newPad = fDigitReader->GetPad();
435 newTime = fDigitReader->GetTime();
436 newRow = fDigitReader->GetRow() + rowOffset;
439 if(newPad != pad)break; //new pad
440 if(newTime != time+1) break; //end of sequence
443 // pad = newpad; is equal
446 }//end loop over sequence
448 //HLTDebug("ended time bin sequence loop: seqcharge=%d readValue=%d", seqcharge, readValue);
449 //HLTDebug("pad=%d newpad=%d current row=%d newrow=%d", pad, newPad, fCurrentRow, newRow);
451 // with active zero suppression zero values are possible
455 //Calculate mean of sequence:
458 seqmean = seqaverage/seqcharge;
460 LOG(AliHLTTPCLog::kFatal,"AliHLTTPCClusterFinder::ProcessRow","Data")
461 <<"Error in data given to the cluster finder"<<ENDLOG;
466 //Calculate mean in pad direction:
467 Int_t padmean = seqcharge*pad;
468 Int_t paderror = pad*padmean;
470 //Compare with results on previous pad:
471 for(UInt_t p=0; p<nprevious && p<kPadArraySize && ncurrent<kPadArraySize; p++){
473 //dont merge sequences on the same pad twice
474 if(previousPt[p]->fLastMergedPad==pad) continue;
476 Int_t difference = seqmean - previousPt[p]->fMean;
477 if(difference < -fMatch) break;
479 if(difference <= fMatch){ //There is a match here!!
480 AliClusterData *local = previousPt[p];
483 if(seqcharge > local->fLastCharge){
484 if(local->fChargeFalling){ //The previous pad was falling
485 break; //create a new cluster
488 else local->fChargeFalling = 1;
489 local->fLastCharge = seqcharge;
492 //Don't create a new cluster, because we found a match
495 //Update cluster on current pad with the matching one:
496 local->fTotalCharge += seqcharge;
497 local->fPad += padmean;
498 local->fPad2 += paderror;
499 local->fTime += seqaverage;
500 local->fTime2 += seqerror;
501 local->fMean = seqmean;
502 local->fFlags++; //means we have more than one pad
503 local->fLastMergedPad = pad;
505 currentPt[ncurrent] = local;
509 } //Checking for match at previous pad
510 } //Loop over results on previous pad.
512 if(newcluster && ncurrent<kPadArraySize){
513 //Start a new cluster. Add it to the clusterlist, and update
514 //the list of pointers to clusters in current pad.
515 //current pad will be previous pad on next pad.
517 //Add to the clusterlist:
518 AliClusterData *tmp = &clusterlist[ntotal];
519 tmp->fTotalCharge = seqcharge;
521 tmp->fPad2 = paderror;
522 tmp->fTime = seqaverage;
523 tmp->fTime2 = seqerror;
524 tmp->fMean = seqmean;
525 tmp->fFlags = 0; //flags for single pad clusters
526 tmp->fLastMergedPad = pad;
529 tmp->fChargeFalling = 0;
530 tmp->fLastCharge = seqcharge;
533 //Update list of pointers to previous pad:
534 currentPt[ncurrent] = &clusterlist[ntotal];
540 if(newbin >= 0) goto redo;
542 // to prevent endless loop
543 if(time >= AliHLTTPCTransform::GetNTimeBins()){
544 HLTWarning("Timebin (%d) out of range (%d)", time, AliHLTTPCTransform::GetNTimeBins());
549 if(!readValue) break; //No more value
551 if (ntotal>=kClusterListSize || ncurrent>=kPadArraySize) {
552 HLTWarning("pad array size exceeded ntotal=%d ncurrent=%d, skip rest of the data", ntotal, ncurrent);
556 if(fCurrentRow != newRow){
557 WriteClusters(ntotal,clusterlist);
567 fCurrentRow = newRow;
573 } // END while(readValue)
575 WriteClusters(ntotal,clusterlist);
577 HLTInfo("ClusterFinder found %d clusters in slice %d patch %d", fNClusters, fCurrentSlice, fCurrentPatch);
581 void AliHLTTPCClusterFinder::WriteClusters(Int_t nclusters,AliClusterData *list)
583 //write cluster to output pointer
584 Int_t thisrow,thissector;
585 UInt_t counter = fNClusters;
587 for(int j=0; j<nclusters; j++)
592 if(!list[j].fFlags) continue; //discard single pad clusters
593 if(list[j].fTotalCharge < fThreshold) continue; //noise cluster
596 Float_t fpad =(Float_t)list[j].fPad / list[j].fTotalCharge;
597 Float_t fpad2=fXYErr*fXYErr; //fixed given error
598 Float_t ftime =(Float_t)list[j].fTime / list[j].fTotalCharge;
599 Float_t ftime2=fZErr*fZErr; //fixed given error
603 fCurrentRow=list[j].fRow;
606 if(fCalcerr) { //calc the errors, otherwice take the fixed error
607 Int_t patch = AliHLTTPCTransform::GetPatch(fCurrentRow);
608 UInt_t q2=list[j].fTotalCharge*list[j].fTotalCharge;
609 Float_t sy2=list[j].fPad2 * list[j].fTotalCharge - list[j].fPad * list[j].fPad;
612 LOG(AliHLTTPCLog::kError,"AliHLTTPCClusterFinder::WriteClusters","Cluster width")
613 <<"SigmaY2 negative "<<sy2<<" on row "<<fCurrentRow<<" "<<fpad<<" "<<ftime<<ENDLOG;
617 fpad2 = (sy2 + 1./12)*AliHLTTPCTransform::GetPadPitchWidth(patch)*AliHLTTPCTransform::GetPadPitchWidth(patch);
619 fpad2*=0.108; //constants are from offline studies
623 } else fpad2=sy2; //take the width not the error
625 Float_t sz2=list[j].fTime2*list[j].fTotalCharge - list[j].fTime*list[j].fTime;
628 LOG(AliHLTTPCLog::kError,"AliHLTTPCClusterFinder::WriteClusters","Cluster width")
629 <<"SigmaZ2 negative "<<sz2<<" on row "<<fCurrentRow<<" "<<fpad<<" "<<ftime<<ENDLOG;
633 ftime2 = (sz2 + 1./12)*AliHLTTPCTransform::GetZWidth()*AliHLTTPCTransform::GetZWidth();
635 ftime2 *= 0.169; //constants are from offline studies
639 } else ftime2=sz2; //take the width, not the error
643 cout<<"WriteCluster: padrow "<<fCurrentRow<<" pad "<<fpad << " +- "<<fpad2<<" time "<<ftime<<" +- "<<ftime2<<" charge "<<list[j].fTotalCharge<<endl;
646 AliHLTTPCTransform::Slice2Sector(fCurrentSlice,fCurrentRow,thissector,thisrow);
647 AliHLTTPCTransform::Raw2Local(xyz,thissector,thisrow,fpad,ftime);
649 if(xyz[0]==0) LOG(AliHLTTPCLog::kError,"AliHLTTPCClustFinder","Cluster Finder")
650 <<AliHLTTPCLog::kDec<<"Zero cluster"<<ENDLOG;
651 if(fNClusters >= fMaxNClusters)
653 LOG(AliHLTTPCLog::kError,"AliHLTTPCClustFinder::WriteClusters","Cluster Finder")
654 <<AliHLTTPCLog::kDec<<"Too many clusters "<<fNClusters<<ENDLOG;
658 fSpacePointData[counter].fX = xyz[0];
659 fSpacePointData[counter].fY = xyz[1];
660 fSpacePointData[counter].fZ = xyz[2];
663 fSpacePointData[counter].fX = fCurrentRow;
664 fSpacePointData[counter].fY = fpad;
665 fSpacePointData[counter].fZ = ftime;
668 fSpacePointData[counter].fCharge = list[j].fTotalCharge;
669 fSpacePointData[counter].fPadRow = fCurrentRow;
670 fSpacePointData[counter].fSigmaY2 = fpad2;
671 fSpacePointData[counter].fSigmaZ2 = ftime2;
673 fSpacePointData[counter].fUsed = kFALSE; // only used / set in AliHLTTPCDisplay
674 fSpacePointData[counter].fTrackN = -1; // only used / set in AliHLTTPCDisplay
676 Int_t patch=fCurrentPatch;
677 if(patch==-1) patch=0; //never store negative patch number
678 fSpacePointData[counter].fID = counter
679 +((fCurrentSlice&0x7f)<<25)+((patch&0x7)<<22);//Uli
683 GetTrackID((Int_t)rint(fpad),(Int_t)rint(ftime),trackID);
685 fSpacePointData[counter].fTrackID[0] = trackID[0];
686 fSpacePointData[counter].fTrackID[1] = trackID[1];
687 fSpacePointData[counter].fTrackID[2] = trackID[2];
689 //cout<<"padrow "<<fCurrentRow<<" pad "<<(Int_t)rint(fpad)<<" time "<<(Int_t)rint(ftime)<<" Trackid "<<trackID[0]<<endl;
697 // STILL TO FIX ----------------------------------------------------------------------------
700 void AliHLTTPCClusterFinder::GetTrackID(Int_t pad,Int_t time,Int_t *trackID)
703 AliHLTTPCDigitRowData *rowPt = (AliHLTTPCDigitRowData*)fDigitRowData;
705 trackID[0]=trackID[1]=trackID[2]=-2;
706 //cout<<"Looking for pad "<<pad<<" time "<<time<<endl;
707 for(Int_t i=fFirstRow; i<=fLastRow; i++){
708 if(rowPt->fRow < (UInt_t)fCurrentRow){
709 AliHLTTPCMemHandler::UpdateRowPointer(rowPt);
712 AliHLTTPCDigitData *digPt = (AliHLTTPCDigitData*)rowPt->fDigitData;
713 for(UInt_t j=0; j<rowPt->fNDigit; j++){
714 Int_t cpad = digPt[j].fPad;
715 Int_t ctime = digPt[j].fTime;
716 if(cpad != pad) continue;
717 if(ctime != time) continue;
719 trackID[0] = digPt[j].fTrackID[0];
720 trackID[1] = digPt[j].fTrackID[1];
721 trackID[2] = digPt[j].fTrackID[2];
723 //cout<<"Reading row "<<fCurrentRow<<" pad "<<cpad<<" time "<<ctime<<" trackID "<<digPt[j].fTrackID[0]<<endl;
731 //----------------------------------Methods for the new unsorted way of reading the data --------------------------------
733 void AliHLTTPCClusterFinder::SetPadArray(AliHLTTPCPadArray * padArray){
737 void AliHLTTPCClusterFinder::ReadDataUnsorted(void* ptr,unsigned long size){
739 fPtr = (UChar_t*)ptr;
742 fDigitReader->InitBlock(fPtr,fSize,fFirstRow,fLastRow,fCurrentPatch,fCurrentSlice);
744 fPadArray->SetDigitReader(fDigitReader);
745 fPadArray->ReadData();
747 void AliHLTTPCClusterFinder::FindClusters(){
748 fPadArray->FindClusterCandidates();
749 fPadArray->FindClusters(fMatch);
751 AliClusterData * clusterlist = new AliClusterData[fPadArray->fClusters.size()]; //Clusterlist
752 for(int i=0;i<fPadArray->fClusters.size();i++){
753 clusterlist[i].fTotalCharge = fPadArray->fClusters[i].fTotalCharge;
754 clusterlist[i].fPad = fPadArray->fClusters[i].fPad;
755 clusterlist[i].fPad2 = fPadArray->fClusters[i].fPad2;
756 clusterlist[i].fTime = fPadArray->fClusters[i].fTime;
757 clusterlist[i].fTime2 = fPadArray->fClusters[i].fTime2;
758 clusterlist[i].fMean = fPadArray->fClusters[i].fMean;
759 clusterlist[i].fFlags = fPadArray->fClusters[i].fFlags;
760 clusterlist[i].fChargeFalling = fPadArray->fClusters[i].fChargeFalling;
761 clusterlist[i].fLastCharge = fPadArray->fClusters[i].fLastCharge;
762 clusterlist[i].fLastMergedPad = fPadArray->fClusters[i].fLastMergedPad;
763 clusterlist[i].fRow = fPadArray->fClusters[i].fRowNumber;
765 WriteClusters(fPadArray->fClusters.size(),clusterlist);
766 delete [] clusterlist;
767 fPadArray->DataToDefault();
769 void AliHLTTPCClusterFinder::WriteClusters(Int_t nclusters,AliHLTTPCClusters *list)//This is used when using the AliHLTTPCClusters class for cluster data
771 //write cluster to output pointer
772 Int_t thisrow,thissector;
773 UInt_t counter = fNClusters;
775 for(int j=0; j<nclusters; j++)
777 if(!list[j].fFlags) continue; //discard single pad clusters
778 if(list[j].fTotalCharge < fThreshold) continue; //noise cluster
781 Float_t fpad =(Float_t)list[j].fPad / list[j].fTotalCharge;
782 Float_t fpad2=fXYErr*fXYErr; //fixed given error
783 Float_t ftime =(Float_t)list[j].fTime / list[j].fTotalCharge;
784 Float_t ftime2=fZErr*fZErr; //fixed given error
787 if(fCalcerr) { //calc the errors, otherwice take the fixed error
788 Int_t patch = AliHLTTPCTransform::GetPatch(fCurrentRow);
789 UInt_t q2=list[j].fTotalCharge*list[j].fTotalCharge;
790 Float_t sy2=list[j].fPad2 * list[j].fTotalCharge - list[j].fPad * list[j].fPad;
793 LOG(AliHLTTPCLog::kError,"AliHLTTPCClusterFinder::WriteClusters","Cluster width")
794 <<"SigmaY2 negative "<<sy2<<" on row "<<fCurrentRow<<" "<<fpad<<" "<<ftime<<ENDLOG;
798 fpad2 = (sy2 + 1./12)*AliHLTTPCTransform::GetPadPitchWidth(patch)*AliHLTTPCTransform::GetPadPitchWidth(patch);
800 fpad2*=0.108; //constants are from offline studies
804 } else fpad2=sy2; //take the width not the error
806 Float_t sz2=list[j].fTime2*list[j].fTotalCharge - list[j].fTime*list[j].fTime;
809 LOG(AliHLTTPCLog::kError,"AliHLTTPCClusterFinder::WriteClusters","Cluster width")
810 <<"SigmaZ2 negative "<<sz2<<" on row "<<fCurrentRow<<" "<<fpad<<" "<<ftime<<ENDLOG;
814 ftime2 = (sz2 + 1./12)*AliHLTTPCTransform::GetZWidth()*AliHLTTPCTransform::GetZWidth();
816 ftime2 *= 0.169; //constants are from offline studies
820 } else ftime2=sz2; //take the width, not the error
824 cout<<"WriteCluster: padrow "<<fCurrentRow<<" pad "<<fpad << " +- "<<fpad2<<" time "<<ftime<<" +- "<<ftime2<<" charge "<<list[j].fTotalCharge<<endl;
827 AliHLTTPCTransform::Slice2Sector(fCurrentSlice,fCurrentRow,thissector,thisrow);
828 AliHLTTPCTransform::Raw2Local(xyz,thissector,thisrow,fpad,ftime);
830 if(xyz[0]==0) LOG(AliHLTTPCLog::kError,"AliHLTTPCClustFinder","Cluster Finder")
831 <<AliHLTTPCLog::kDec<<"Zero cluster"<<ENDLOG;
832 if(fNClusters >= fMaxNClusters)
834 LOG(AliHLTTPCLog::kError,"AliHLTTPCClustFinder::WriteClusters","Cluster Finder")
835 <<AliHLTTPCLog::kDec<<"Too many clusters "<<fNClusters<<ENDLOG;
839 fSpacePointData[counter].fX = xyz[0];
840 fSpacePointData[counter].fY = xyz[1];
841 fSpacePointData[counter].fZ = xyz[2];
844 fSpacePointData[counter].fX = fCurrentRow;
845 fSpacePointData[counter].fY = fpad;
846 fSpacePointData[counter].fZ = ftime;
849 fSpacePointData[counter].fCharge = list[j].fTotalCharge;
850 fSpacePointData[counter].fPadRow = fCurrentRow;
851 fSpacePointData[counter].fSigmaY2 = fpad2;
852 fSpacePointData[counter].fSigmaZ2 = ftime2;
854 fSpacePointData[counter].fUsed = kFALSE; // only used / set in AliHLTTPCDisplay
855 fSpacePointData[counter].fTrackN = -1; // only used / set in AliHLTTPCDisplay
857 Int_t patch=fCurrentPatch;
858 if(patch==-1) patch=0; //never store negative patch number
859 fSpacePointData[counter].fID = counter
860 +((fCurrentSlice&0x7f)<<25)+((patch&0x7)<<22);//Uli
864 GetTrackID((Int_t)rint(fpad),(Int_t)rint(ftime),trackID);
866 fSpacePointData[counter].fTrackID[0] = trackID[0];
867 fSpacePointData[counter].fTrackID[1] = trackID[1];
868 fSpacePointData[counter].fTrackID[2] = trackID[2];
870 //cout<<"padrow "<<fCurrentRow<<" pad "<<(Int_t)rint(fpad)<<" time "<<(Int_t)rint(ftime)<<" Trackid "<<trackID[0]<<endl;