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 *
9 //* Developers: Kenneth Aamodt <kenneth.aamodt@student.uib.no> *
11 //* for The ALICE HLT Project. *
13 //* Permission to use, copy, modify and distribute this software and its *
14 //* documentation strictly for non-commercial purposes is hereby granted *
15 //* without fee, provided that the above copyright notice appears in all *
16 //* copies and that both the copyright notice and this permission notice *
17 //* appear in the supporting documentation. The authors make no claims *
18 //* about the suitability of this software for any purpose. It is *
19 //* provided "as is" without express or implied warranty. *
20 //**************************************************************************
22 /** @file AliHLTTPCClusterFinder.cxx
23 @author Kenneth Aamodt, Kalliopi Kanaki
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 "AliHLTTPCSpacePointData.h"
34 #include "AliHLTTPCMemHandler.h"
35 #include "AliHLTTPCPad.h"
42 ClassImp(AliHLTTPCClusterFinder)
44 AliHLTTPCClusterFinder::AliHLTTPCClusterFinder()
46 fClustersHWAddressVector(),
48 fSpacePointData(NULL),
70 fVectorInitialized(kFALSE),
72 fNumberOfPadsInRow(NULL),
74 fRowOfFirstCandidate(0),
75 fDoPadSelection(kFALSE),
77 fLastTimeBin(AliHLTTPCTransform::GetNTimeBins()),
78 fTotalChargeOfPreviousClusterCandidate(0),
79 fChargeOfCandidatesFalling(kFALSE)
84 AliHLTTPCClusterFinder::~AliHLTTPCClusterFinder()
87 if(fVectorInitialized){
88 DeInitializePadArray();
90 if(fNumberOfPadsInRow){
91 delete [] fNumberOfPadsInRow;
92 fNumberOfPadsInRow=NULL;
96 void AliHLTTPCClusterFinder::InitSlice(Int_t slice,Int_t patch,Int_t firstrow, Int_t lastrow,Int_t nmaxpoints)
100 fMaxNClusters = nmaxpoints;
101 fCurrentSlice = slice;
102 fCurrentPatch = patch;
103 fFirstRow = firstrow;
107 void AliHLTTPCClusterFinder::InitializePadArray(){
108 // see header file for class documentation
110 if(fCurrentPatch>5||fCurrentPatch<0){
111 HLTFatal("Patch is not set");
115 HLTDebug("Patch number=%d",fCurrentPatch);
117 fFirstRow = AliHLTTPCTransform::GetFirstRow(fCurrentPatch);
118 fLastRow = AliHLTTPCTransform::GetLastRow(fCurrentPatch);
120 fNumberOfRows=fLastRow-fFirstRow+1;
121 fNumberOfPadsInRow= new UInt_t[fNumberOfRows];
123 memset( fNumberOfPadsInRow, 0, sizeof(Int_t)*(fNumberOfRows));
125 for(UInt_t i=0;i<fNumberOfRows;i++){
126 fNumberOfPadsInRow[i]=AliHLTTPCTransform::GetNPads(i+fFirstRow);
127 AliHLTTPCPadVector tmpRow;
128 for(UInt_t j=0;j<=fNumberOfPadsInRow[i];j++){
129 AliHLTTPCPad *tmpPad = new AliHLTTPCPad(2);
131 tmpRow.push_back(tmpPad);
133 fRowPadVector.push_back(tmpRow);
135 fVectorInitialized=kTRUE;
138 Int_t AliHLTTPCClusterFinder::DeInitializePadArray()
140 // see header file for class documentation
141 for(UInt_t i=0;i<fNumberOfRows;i++){
142 for(UInt_t j=0;j<=fNumberOfPadsInRow[i];j++){
143 delete fRowPadVector[i][j];
144 fRowPadVector[i][j]=NULL;
146 fRowPadVector[i].clear();
148 fRowPadVector.clear();
153 void AliHLTTPCClusterFinder::InitSlice(Int_t slice,Int_t patch,Int_t nmaxpoints)
157 fMaxNClusters = nmaxpoints;
158 fCurrentSlice = slice;
159 fCurrentPatch = patch;
160 fFirstRow=AliHLTTPCTransform::GetFirstRow(patch);
161 fLastRow=AliHLTTPCTransform::GetLastRow(patch);
164 void AliHLTTPCClusterFinder::SetOutputArray(AliHLTTPCSpacePointData *pt)
166 //set pointer to output
167 fSpacePointData = pt;
170 void AliHLTTPCClusterFinder::Read(void* ptr,unsigned long size){
172 fPtr = (UChar_t*)ptr;
176 void AliHLTTPCClusterFinder::ProcessDigits()
179 bool readValue = true;
182 UShort_t time=0,newTime=0;
183 UInt_t pad=0,newPad=0;
184 AliHLTTPCSignal_t charge=0;
188 // initialize block for reading packed data
189 iResult=fDigitReader->InitBlock(fPtr,fSize,fFirstRow,fLastRow,fCurrentPatch,fCurrentSlice);
190 if (iResult<0) return;
192 readValue = fDigitReader->Next();
194 // Matthias 08.11.2006 the following return would cause termination without writing the
195 // ClusterData and thus would block the component. I just want to have the commented line
196 // here for information
197 //if (!readValue)return;
199 pad = fDigitReader->GetPad();
200 time = fDigitReader->GetTime();
201 fCurrentRow = fDigitReader->GetRow();
203 if ( fCurrentPatch >= 2 ) // Outer sector, patches 2, 3, 4, 5
204 rowOffset = AliHLTTPCTransform::GetFirstRow( 2 );
206 fCurrentRow += rowOffset;
208 UInt_t lastpad = 123456789;
209 const UInt_t kPadArraySize=5000;
210 const UInt_t kClusterListSize=10000;
211 AliClusterData *pad1[kPadArraySize]; //2 lists for internal memory=2pads
212 AliClusterData *pad2[kPadArraySize]; //2 lists for internal memory=2pads
213 AliClusterData clusterlist[kClusterListSize]; //Clusterlist
215 AliClusterData **currentPt; //List of pointers to the current pad
216 AliClusterData **previousPt; //List of pointers to the previous pad
219 UInt_t nprevious=0,ncurrent=0,ntotal=0;
221 /* quick implementation of baseline calculation and zero suppression
222 open a pad object for each pad and delete it after processing.
223 later a list of pad objects with base line history can be used
224 The whole thing only works if we really get unprocessed raw data, if
225 the data is already zero suppressed, there might be gaps in the time
228 Int_t gatingGridOffset=50;
230 gatingGridOffset=fFirstTimeBin;
232 AliHLTTPCPad baseline(gatingGridOffset, AliHLTTPCTransform::GetNTimeBins());
233 // just to make later conversion to a list of objects easier
234 AliHLTTPCPad* pCurrentPad=NULL;
236 if (fSignalThreshold>=0) {
237 pCurrentPad=&baseline;
238 baseline.SetThreshold(fSignalThreshold);
241 while ( readValue!=0 && iResult>=0){ // Reads through all digits in block
248 if(currentPt == pad2){
256 nprevious = ncurrent;
258 if(pad != lastpad+1){
259 //this happens if there is a pad with no signal.
260 nprevious = ncurrent = 0;
265 Bool_t newcluster = kTRUE;
266 UInt_t seqcharge=0,seqaverage=0,seqerror=0;
267 AliHLTTPCSignal_t lastcharge=0;
268 UInt_t bLastWasFalling=0;
273 redo: //This is a goto.
284 while(iResult>=0){ //Loop over time bins of current pad
285 // read all the values for one pad at once to calculate the base line
287 if (!pCurrentPad->IsStarted()) {
288 //HLTDebug("reading data for pad %d, padrow %d", fDigitReader->GetPad(), fDigitReader->GetRow()+rowOffset);
289 pCurrentPad->SetID(fDigitReader->GetRow()+rowOffset,fDigitReader->GetPad());
290 if ((pCurrentPad->StartEvent())>=0) {
292 if ((fDigitReader->GetRow()+rowOffset)!=pCurrentPad->GetRowNumber()) break;
293 if (fDigitReader->GetPad()!=pCurrentPad->GetPadNumber()) break;
294 pCurrentPad->SetRawData(fDigitReader->GetTime(), fDigitReader->GetSignal());
295 //HLTDebug("set raw data to pad: bin %d charge %d", fDigitReader->GetTime(), fDigitReader->GetSignal());
296 } while ((readValue = fDigitReader->Next())!=0);
298 pCurrentPad->CalculateBaseLine(AliHLTTPCTransform::GetNTimeBins()/2);
299 if (pCurrentPad->Next(kTRUE/*do zero suppression*/)==0) {
300 //HLTDebug("no data available after zero suppression");
301 pCurrentPad->StopEvent();
302 pCurrentPad->ResetHistory();
305 time=pCurrentPad->GetCurrentPosition();
306 if (time>pCurrentPad->GetSize()) {
307 HLTError("invalid time bin for pad");
313 Float_t occupancy=pCurrentPad->GetOccupancy();
314 //HLTDebug("pad %d occupancy level: %f", pCurrentPad->GetPadNumber(), occupancy);
315 if ( occupancy < fOccupancyLimit ) {
316 charge = pCurrentPad->GetCorrectedData();
319 //HLTDebug("ignoring pad %d with occupancy level %f", pCurrentPad->GetPadNumber(), occupancy);
322 charge = fDigitReader->GetSignal();
324 //HLTDebug("get next charge value: position %d charge %d", time, charge);
328 if (fDigitReader->GetRow() == 90){
329 ///// LOG(AliHLTTPCLog::kFatal,"AliHLTTPCClusterFinder::Row","row90") << "PAD=" << fDigitReader->GetPad() << " TIME=" << fDigitReader->GetTime()
330 // << " SIGNAL=" << fDigitReader->GetSignal() << ENDLOG;
334 if(time >= AliHLTTPCTransform::GetNTimeBins()){
335 HLTWarning("Pad %d: Timebin (%d) out of range (%d)", pad, time, AliHLTTPCTransform::GetNTimeBins());
340 //Get the current ADC-value
343 //Check if the last pixel in the sequence is smaller than this
344 if(charge > lastcharge){
350 else bLastWasFalling = 1; //last pixel was larger than this
354 //Sum the total charge of this sequence
356 seqaverage += time*charge;
357 seqerror += time*time*charge;
361 if((pCurrentPad->Next(kTRUE/*do zero suppression*/))==0) {
362 pCurrentPad->StopEvent();
363 pCurrentPad->ResetHistory();
365 newPad = fDigitReader->GetPad();
366 newTime = fDigitReader->GetTime();
367 newRow = fDigitReader->GetRow() + rowOffset;
372 newPad=pCurrentPad->GetPadNumber();
373 newTime=pCurrentPad->GetCurrentPosition();
374 newRow=pCurrentPad->GetRowNumber();
376 readValue = fDigitReader->Next();
377 //Check where to stop:
378 if(!readValue) break; //No more value
380 newPad = fDigitReader->GetPad();
381 newTime = fDigitReader->GetTime();
382 newRow = fDigitReader->GetRow() + rowOffset;
385 if(newPad != pad)break; //new pad
386 if(newTime != time+1) break; //end of sequence
389 // pad = newpad; is equal
392 }//end loop over sequence
394 //HLTDebug("ended time bin sequence loop: seqcharge=%d readValue=%d", seqcharge, readValue);
395 //HLTDebug("pad=%d newpad=%d current row=%d newrow=%d", pad, newPad, fCurrentRow, newRow);
397 // with active zero suppression zero values are possible
401 //Calculate mean of sequence:
404 seqmean = seqaverage/seqcharge;
406 LOG(AliHLTTPCLog::kFatal,"AliHLTTPCClusterFinder::ProcessRow","Data")
407 <<"Error in data given to the cluster finder"<<ENDLOG;
412 //Calculate mean in pad direction:
413 Int_t padmean = seqcharge*pad;
414 Int_t paderror = pad*padmean;
416 //Compare with results on previous pad:
417 for(UInt_t p=0; p<nprevious && p<kPadArraySize && ncurrent<kPadArraySize; p++){
419 //dont merge sequences on the same pad twice
420 if(previousPt[p]->fLastMergedPad==pad) continue;
422 Int_t difference = seqmean - previousPt[p]->fMean;
423 if(difference < -fMatch) break;
425 if(difference <= fMatch){ //There is a match here!!
426 AliClusterData *local = previousPt[p];
429 if(seqcharge > local->fLastCharge){
430 if(local->fChargeFalling){ //The previous pad was falling
431 break; //create a new cluster
434 else local->fChargeFalling = 1;
435 local->fLastCharge = seqcharge;
438 //Don't create a new cluster, because we found a match
441 //Update cluster on current pad with the matching one:
442 local->fTotalCharge += seqcharge;
443 local->fPad += padmean;
444 local->fPad2 += paderror;
445 local->fTime += seqaverage;
446 local->fTime2 += seqerror;
447 local->fMean = seqmean;
448 local->fFlags++; //means we have more than one pad
449 local->fLastMergedPad = pad;
451 currentPt[ncurrent] = local;
455 } //Checking for match at previous pad
456 } //Loop over results on previous pad.
458 if(newcluster && ncurrent<kPadArraySize){
459 //Start a new cluster. Add it to the clusterlist, and update
460 //the list of pointers to clusters in current pad.
461 //current pad will be previous pad on next pad.
463 //Add to the clusterlist:
464 AliClusterData *tmp = &clusterlist[ntotal];
465 tmp->fTotalCharge = seqcharge;
467 tmp->fPad2 = paderror;
468 tmp->fTime = seqaverage;
469 tmp->fTime2 = seqerror;
470 tmp->fMean = seqmean;
471 tmp->fFlags = 0; //flags for single pad clusters
472 tmp->fLastMergedPad = pad;
475 tmp->fChargeFalling = 0;
476 tmp->fLastCharge = seqcharge;
479 //Update list of pointers to previous pad:
480 currentPt[ncurrent] = &clusterlist[ntotal];
486 if(newbin >= 0) goto redo;
488 // to prevent endless loop
489 if(time >= AliHLTTPCTransform::GetNTimeBins()){
490 HLTWarning("Timebin (%d) out of range (%d)", time, AliHLTTPCTransform::GetNTimeBins());
495 if(!readValue) break; //No more value
497 if (ntotal>=kClusterListSize || ncurrent>=kPadArraySize) {
498 HLTWarning("pad array size exceeded ntotal=%d ncurrent=%d, skip rest of the data", ntotal, ncurrent);
502 if(fCurrentRow != newRow){
503 WriteClusters(ntotal,clusterlist);
513 fCurrentRow = newRow;
519 } // END while(readValue)
521 WriteClusters(ntotal,clusterlist);
523 HLTInfo("ClusterFinder found %d clusters in slice %d patch %d", fNClusters, fCurrentSlice, fCurrentPatch);
527 void AliHLTTPCClusterFinder::WriteClusters(Int_t nclusters,AliClusterData *list)
529 //write cluster to output pointer
530 Int_t thisrow=-1,thissector=-1;
531 UInt_t counter = fNClusters;
533 for(int j=0; j<nclusters; j++)
538 if(!list[j].fFlags) continue; //discard single pad clusters
539 if(list[j].fTotalCharge < fThreshold) continue; //noise cluster
542 Float_t fpad =(Float_t)list[j].fPad / list[j].fTotalCharge;
543 Float_t fpad2=fXYErr*fXYErr; //fixed given error
544 Float_t ftime =(Float_t)list[j].fTime / list[j].fTotalCharge;
545 Float_t ftime2=fZErr*fZErr; //fixed given error
550 fCurrentRow=list[j].fRow;
554 if(fCalcerr) { //calc the errors, otherwice take the fixed error
555 Int_t patch = AliHLTTPCTransform::GetPatch(fCurrentRow);
556 UInt_t q2=list[j].fTotalCharge*list[j].fTotalCharge;
557 Float_t sy2=list[j].fPad2 * list[j].fTotalCharge - list[j].fPad * list[j].fPad;
560 LOG(AliHLTTPCLog::kError,"AliHLTTPCClusterFinder::WriteClusters","Cluster width")
561 <<"SigmaY2 negative "<<sy2<<" on row "<<fCurrentRow<<" "<<fpad<<" "<<ftime<<ENDLOG;
565 fpad2 = (sy2 + 1./12)*AliHLTTPCTransform::GetPadPitchWidth(patch)*AliHLTTPCTransform::GetPadPitchWidth(patch);
567 fpad2*=0.108; //constants are from offline studies
571 } else fpad2=sy2; //take the width not the error
573 Float_t sz2=list[j].fTime2*list[j].fTotalCharge - list[j].fTime*list[j].fTime;
576 LOG(AliHLTTPCLog::kError,"AliHLTTPCClusterFinder::WriteClusters","Cluster width")
577 <<"SigmaZ2 negative "<<sz2<<" on row "<<fCurrentRow<<" "<<fpad<<" "<<ftime<<ENDLOG;
581 ftime2 = (sz2 + 1./12)*AliHLTTPCTransform::GetZWidth()*AliHLTTPCTransform::GetZWidth();
583 ftime2 *= 0.169; //constants are from offline studies
587 } else ftime2=sz2; //take the width, not the error
591 HLTInfo("WriteCluster: padrow %d pad %d +- %d time +- %d charge %d",fCurrentRow, fpad, fpad2, ftime, ftime2, list[j].fTotalCharge);
594 AliHLTTPCTransform::Slice2Sector(fCurrentSlice,fCurrentRow,thissector,thisrow);
595 AliHLTTPCTransform::Raw2Local(xyz,thissector,thisrow,fpad,ftime);
597 if(xyz[0]==0) LOG(AliHLTTPCLog::kError,"AliHLTTPCClustFinder","Cluster Finder")
598 <<AliHLTTPCLog::kDec<<"Zero cluster"<<ENDLOG;
599 if(fNClusters >= fMaxNClusters)
601 LOG(AliHLTTPCLog::kError,"AliHLTTPCClustFinder::WriteClusters","Cluster Finder")
602 <<AliHLTTPCLog::kDec<<"Too many clusters "<<fNClusters<<ENDLOG;
606 fSpacePointData[counter].fX = xyz[0];
607 // fSpacePointData[counter].fY = xyz[1];
608 if(fCurrentSlice<18){
609 fSpacePointData[counter].fY = xyz[1];
612 fSpacePointData[counter].fY = -1*xyz[1];
614 fSpacePointData[counter].fZ = xyz[2];
617 fSpacePointData[counter].fX = fCurrentRow;
618 fSpacePointData[counter].fY = fpad;
619 fSpacePointData[counter].fZ = ftime;
622 fSpacePointData[counter].fCharge = list[j].fTotalCharge;
623 fSpacePointData[counter].fPadRow = fCurrentRow;
624 fSpacePointData[counter].fSigmaY2 = fpad2;
625 fSpacePointData[counter].fSigmaZ2 = ftime2;
627 fSpacePointData[counter].fMaxQ = list[j].fQMax;
629 fSpacePointData[counter].fUsed = kFALSE; // only used / set in AliHLTTPCDisplay
630 fSpacePointData[counter].fTrackN = -1; // only used / set in AliHLTTPCDisplay
632 Int_t patch=fCurrentPatch;
633 if(patch==-1) patch=0; //never store negative patch number
634 fSpacePointData[counter].fID = counter
635 +((fCurrentSlice&0x7f)<<25)+((patch&0x7)<<22);//Uli
639 GetTrackID((Int_t)rint(fpad),(Int_t)rint(ftime),trackID);
641 fSpacePointData[counter].fTrackID[0] = trackID[0];
642 fSpacePointData[counter].fTrackID[1] = trackID[1];
643 fSpacePointData[counter].fTrackID[2] = trackID[2];
652 // STILL TO FIX ----------------------------------------------------------------------------
655 void AliHLTTPCClusterFinder::GetTrackID(Int_t pad,Int_t time,Int_t *trackID)
658 AliHLTTPCDigitRowData *rowPt = (AliHLTTPCDigitRowData*)fDigitRowData;
660 trackID[0]=trackID[1]=trackID[2]=-2;
661 for(Int_t i=fFirstRow; i<=fLastRow; i++){
662 if(rowPt->fRow < (UInt_t)fCurrentRow){
663 AliHLTTPCMemHandler::UpdateRowPointer(rowPt);
666 AliHLTTPCDigitData *digPt = (AliHLTTPCDigitData*)rowPt->fDigitData;
667 for(UInt_t j=0; j<rowPt->fNDigit; j++){
668 Int_t cpad = digPt[j].fPad;
669 Int_t ctime = digPt[j].fTime;
670 if(cpad != pad) continue;
671 if(ctime != time) continue;
673 trackID[0] = digPt[j].fTrackID[0];
674 trackID[1] = digPt[j].fTrackID[1];
675 trackID[2] = digPt[j].fTrackID[2];
684 //----------------------------------Methods for the new unsorted way of reading the data --------------------------------
686 void AliHLTTPCClusterFinder::ReadDataUnsorted(void* ptr,unsigned long size)
689 fPtr = (UChar_t*)ptr;
692 if(!fVectorInitialized){
693 InitializePadArray();
696 fDigitReader->InitBlock(fPtr,fSize,fFirstRow,fLastRow,fCurrentPatch,fCurrentSlice);
698 while(fDigitReader->NextChannel()){
699 UInt_t row=fDigitReader->GetRow();
700 UInt_t pad=fDigitReader->GetPad();
702 while(fDigitReader->NextBunch()){
703 if(fDigitReader->GetBunchSize()>1){//to remove single timebin values, this will have to change at some point
704 UInt_t time = fDigitReader->GetTime();
705 if((Int_t)time>=fFirstTimeBin && (Int_t)time+fDigitReader->GetBunchSize()<=fLastTimeBin){
706 const UInt_t *bunchData= fDigitReader->GetSignals();
707 AliHLTTPCClusters candidate;
708 for(Int_t i=0;i<fDigitReader->GetBunchSize();i++){
709 candidate.fTotalCharge+=bunchData[i];
710 candidate.fTime += time*bunchData[i];
711 candidate.fTime2 += time*time*bunchData[i];
712 if(bunchData[i]>candidate.fQMax){
713 candidate.fQMax=bunchData[i];
717 if(candidate.fTotalCharge>0){
718 candidate.fMean=candidate.fTime/candidate.fTotalCharge;
719 candidate.fPad=candidate.fTotalCharge*pad;
720 candidate.fPad2=candidate.fPad*pad;
721 candidate.fLastMergedPad=pad;
722 candidate.fRowNumber=row+fDigitReader->GetRowOffset();
724 fRowPadVector[row][pad]->AddClusterCandidate(candidate);
731 void AliHLTTPCClusterFinder::ReadDataUnsortedDeconvoluteTime(void* ptr,unsigned long size)
734 fPtr = (UChar_t*)ptr;
737 if(!fVectorInitialized){
738 InitializePadArray();
741 fDigitReader->InitBlock(fPtr,fSize,fFirstRow,fLastRow,fCurrentPatch,fCurrentSlice);
743 while(fDigitReader->NextChannel()){
744 UInt_t row=fDigitReader->GetRow();
745 UInt_t pad=fDigitReader->GetPad();
747 while(fDigitReader->NextBunch()){
748 if(fDigitReader->GetBunchSize()>1){//to remove single timebin values, this will have to change at some point
749 UInt_t time = fDigitReader->GetTime();
750 if((Int_t)time>=fFirstTimeBin && (Int_t)time+fDigitReader->GetBunchSize()<=fLastTimeBin){
751 Int_t indexInBunchData=0;
752 Bool_t moreDataInBunch=kFALSE;
754 Bool_t signalFalling=kFALSE;
755 const UInt_t *bunchData= fDigitReader->GetSignals();
757 AliHLTTPCClusters candidate;
758 for(Int_t i=indexInBunchData;i<fDigitReader->GetBunchSize();i++){
759 // Checks if one need to deconvolute the signals
760 if(bunchData[i]>prevSignal && signalFalling==kTRUE){
761 if(i<fDigitReader->GetBunchSize()-1){ // means there are more than one signal left in the bunch
762 moreDataInBunch=kTRUE;
768 // Checks if the signal is 0, then quit processing the data.
769 if(bunchData[i]==0 && i<fDigitReader->GetBunchSize()-1){//means we have 0 data fom the rcu, might happen depending on the configuration settings
770 moreDataInBunch=kTRUE;
775 if(prevSignal>bunchData[i]){//means the peak of the signal has been reached and deconvolution will happen if the signal rise again.
778 candidate.fTotalCharge+=bunchData[i];
779 candidate.fTime += time*bunchData[i];
780 candidate.fTime2 += time*time*bunchData[i];
781 if(bunchData[i]>candidate.fQMax){
782 candidate.fQMax=bunchData[i];
785 prevSignal=bunchData[i];
789 if(candidate.fTotalCharge>0){
790 candidate.fMean=candidate.fTime/candidate.fTotalCharge;
791 candidate.fPad=candidate.fTotalCharge*pad;
792 candidate.fPad2=candidate.fPad*pad;
793 candidate.fLastMergedPad=pad;
794 candidate.fRowNumber=row+fDigitReader->GetRowOffset();
796 fRowPadVector[row][pad]->AddClusterCandidate(candidate);
797 if(indexInBunchData<fDigitReader->GetBunchSize()-1){
798 moreDataInBunch=kFALSE;
800 }while(moreDataInBunch);
807 Bool_t AliHLTTPCClusterFinder::ComparePads(AliHLTTPCPad *nextPad,AliHLTTPCClusters* cluster,Int_t nextPadToRead){
808 //Checking if we have a match on the next pad
809 for(UInt_t candidateNumber=0;candidateNumber<nextPad->fClusterCandidates.size();candidateNumber++){
810 AliHLTTPCClusters *candidate =&nextPad->fClusterCandidates[candidateNumber];
811 if(cluster->fMean-candidate->fMean==1 || candidate->fMean-cluster->fMean==1 || cluster->fMean-candidate->fMean==0){
813 if(candidate->fTotalCharge<fTotalChargeOfPreviousClusterCandidate){//peak is reached
814 fChargeOfCandidatesFalling=kTRUE;
816 if(candidate->fTotalCharge>fTotalChargeOfPreviousClusterCandidate && fChargeOfCandidatesFalling==kTRUE){//we have deconvolution
820 cluster->fMean=candidate->fMean;
821 cluster->fTotalCharge+=candidate->fTotalCharge;
822 cluster->fTime += candidate->fTime;
823 cluster->fTime2 += candidate->fTime2;
824 cluster->fPad+=candidate->fPad;
825 cluster->fPad2=candidate->fPad2;
826 cluster->fLastMergedPad=candidate->fPad;
827 if(candidate->fQMax>cluster->fQMax){
828 cluster->fQMax=candidate->fQMax;
832 UInt_t rowNo = nextPad->GetRowNumber();
833 UInt_t padNo = nextPad->GetPadNumber();
835 fRowPadVector[rowNo][padNo-2]->fSelectedPad=kTRUE;
836 fRowPadVector[rowNo][padNo-2]->fHWAddress=(AliHLTUInt16_t)fDigitReader->GetAltroBlockHWaddr(rowNo,padNo-2);
838 fRowPadVector[rowNo][padNo-1]->fSelectedPad=kTRUE;// quick solution to set the first pad to selected
839 fRowPadVector[rowNo][padNo-1]->fHWAddress=(AliHLTUInt16_t)fDigitReader->GetAltroBlockHWaddr(rowNo,padNo-1);
840 fRowPadVector[rowNo][padNo]->fSelectedPad=kTRUE;
841 fRowPadVector[rowNo][padNo]->fHWAddress=(AliHLTUInt16_t)fDigitReader->GetAltroBlockHWaddr(rowNo,padNo);
844 //setting the matched pad to used
845 nextPad->fUsedClusterCandidates[candidateNumber]=1;
847 if(nextPadToRead<(Int_t)fNumberOfPadsInRow[fRowOfFirstCandidate]){
848 nextPad=fRowPadVector[fRowOfFirstCandidate][nextPadToRead];
849 ComparePads(nextPad,cluster,nextPadToRead);
862 Int_t AliHLTTPCClusterFinder::FillHWAddressList(AliHLTUInt16_t *hwaddlist, Int_t maxHWadd){
864 for(UInt_t row=0;row<fNumberOfRows;row++){
865 for(UInt_t pad=0;pad<fNumberOfPadsInRow[row]-1;pad++){
866 if(fRowPadVector[row][pad]->fSelectedPad){
867 if(counter<maxHWadd){
868 hwaddlist[counter]=(AliHLTUInt16_t)fRowPadVector[row][pad]->fHWAddress;
872 HLTWarning("To many hardwareaddresses, skip adding");
881 void AliHLTTPCClusterFinder::FindClusters()
883 // see header file for function documentation
885 AliHLTTPCClusters* tmpCandidate=NULL;
886 for(UInt_t row=0;row<fNumberOfRows;row++){
887 fRowOfFirstCandidate=row;
888 for(UInt_t pad=0;pad<fNumberOfPadsInRow[row];pad++){
889 AliHLTTPCPad *tmpPad=fRowPadVector[row][pad];
890 for(size_t candidate=0;candidate<tmpPad->fClusterCandidates.size();candidate++){
891 if(tmpPad->fUsedClusterCandidates[candidate]){
894 tmpCandidate=&tmpPad->fClusterCandidates[candidate];
895 UInt_t tmpTotalCharge=tmpCandidate->fTotalCharge;
897 ComparePads(fRowPadVector[row][pad+1],tmpCandidate,pad+1);
898 if(tmpCandidate->fTotalCharge>tmpTotalCharge){
900 fClusters.push_back(*tmpCandidate);
903 tmpPad->ClearCandidates();
905 fRowPadVector[row][fNumberOfPadsInRow[row]]->ClearCandidates();
908 HLTInfo("Found %d clusters.",fClusters.size());
910 //TODO: Change so it stores AliHLTTPCSpacePointData directly, instead of this copying
912 AliClusterData * clusterlist = new AliClusterData[fClusters.size()]; //Clusterlist
913 for(unsigned int i=0;i<fClusters.size();i++){
914 clusterlist[i].fTotalCharge = fClusters[i].fTotalCharge;
915 clusterlist[i].fPad = fClusters[i].fPad;
916 clusterlist[i].fPad2 = fClusters[i].fPad2;
917 clusterlist[i].fTime = fClusters[i].fTime;
918 clusterlist[i].fTime2 = fClusters[i].fTime2;
919 clusterlist[i].fMean = fClusters[i].fMean;
920 clusterlist[i].fFlags = fClusters[i].fFlags;
921 clusterlist[i].fChargeFalling = fClusters[i].fChargeFalling;
922 clusterlist[i].fLastCharge = fClusters[i].fLastCharge;
923 clusterlist[i].fLastMergedPad = fClusters[i].fLastMergedPad;
924 clusterlist[i].fRow = fClusters[i].fRowNumber;
927 WriteClusters(fClusters.size(),clusterlist);
928 delete [] clusterlist;
932 void AliHLTTPCClusterFinder::PrintClusters()
934 // see header file for class documentation
935 for(size_t i=0;i<fClusters.size();i++){
936 HLTInfo("Cluster number: %d",i);
937 HLTInfo("Row: %d \t Pad: %d",fClusters[i].fRowNumber,fClusters[i].fPad/fClusters[i].fTotalCharge);
938 HLTInfo("Total Charge: %d",fClusters[i].fTotalCharge);
939 HLTInfo("fPad: %d",fClusters[i].fPad);
940 HLTInfo("PadError: %d",fClusters[i].fPad2);
941 HLTInfo("TimeMean: %d",fClusters[i].fTime/fClusters[i].fTotalCharge);
942 HLTInfo("TimeError: %d",fClusters[i].fTime2);
943 HLTInfo("EndOfCluster:");
947 void AliHLTTPCClusterFinder::WriteClusters(Int_t nclusters,AliHLTTPCClusters *list)//This is used when using the AliHLTTPCClusters class for cluster data
949 //write cluster to output pointer
950 Int_t thisrow,thissector;
951 UInt_t counter = fNClusters;
953 for(int j=0; j<nclusters; j++)
955 if(!list[j].fFlags) continue; //discard single pad clusters
956 if(list[j].fTotalCharge < fThreshold) continue; //noise cluster
959 Float_t fpad =(Float_t)list[j].fPad / list[j].fTotalCharge;
960 Float_t fpad2=fXYErr*fXYErr; //fixed given error
961 Float_t ftime =(Float_t)list[j].fTime / list[j].fTotalCharge;
962 Float_t ftime2=fZErr*fZErr; //fixed given error
965 if(fCalcerr) { //calc the errors, otherwice take the fixed error
966 Int_t patch = AliHLTTPCTransform::GetPatch(fCurrentRow);
967 UInt_t q2=list[j].fTotalCharge*list[j].fTotalCharge;
968 Float_t sy2=list[j].fPad2 * list[j].fTotalCharge - list[j].fPad * list[j].fPad;
971 LOG(AliHLTTPCLog::kError,"AliHLTTPCClusterFinder::WriteClusters","Cluster width")
972 <<"SigmaY2 negative "<<sy2<<" on row "<<fCurrentRow<<" "<<fpad<<" "<<ftime<<ENDLOG;
976 fpad2 = (sy2 + 1./12)*AliHLTTPCTransform::GetPadPitchWidth(patch)*AliHLTTPCTransform::GetPadPitchWidth(patch);
978 fpad2*=0.108; //constants are from offline studies
982 } else fpad2=sy2; //take the width not the error
984 Float_t sz2=list[j].fTime2*list[j].fTotalCharge - list[j].fTime*list[j].fTime;
987 LOG(AliHLTTPCLog::kError,"AliHLTTPCClusterFinder::WriteClusters","Cluster width")
988 <<"SigmaZ2 negative "<<sz2<<" on row "<<fCurrentRow<<" "<<fpad<<" "<<ftime<<ENDLOG;
992 ftime2 = (sz2 + 1./12)*AliHLTTPCTransform::GetZWidth()*AliHLTTPCTransform::GetZWidth();
994 ftime2 *= 0.169; //constants are from offline studies
998 } else ftime2=sz2; //take the width, not the error
1002 HLTInfo("WriteCluster: padrow %d pad %d +- %d time +- %d charge %d",fCurrentRow, fpad, fpad2, ftime, ftime2, list[j].fTotalCharge);
1005 AliHLTTPCTransform::Slice2Sector(fCurrentSlice,fCurrentRow,thissector,thisrow);
1006 AliHLTTPCTransform::Raw2Local(xyz,thissector,thisrow,fpad,ftime);
1008 if(xyz[0]==0) LOG(AliHLTTPCLog::kError,"AliHLTTPCClustFinder","Cluster Finder")
1009 <<AliHLTTPCLog::kDec<<"Zero cluster"<<ENDLOG;
1010 if(fNClusters >= fMaxNClusters)
1012 LOG(AliHLTTPCLog::kError,"AliHLTTPCClustFinder::WriteClusters","Cluster Finder")
1013 <<AliHLTTPCLog::kDec<<"Too many clusters "<<fNClusters<<ENDLOG;
1017 fSpacePointData[counter].fX = xyz[0];
1018 // fSpacePointData[counter].fY = xyz[1];
1019 if(fCurrentSlice<18){
1020 fSpacePointData[counter].fY = xyz[1];
1023 fSpacePointData[counter].fY = -1*xyz[1];
1025 fSpacePointData[counter].fZ = xyz[2];
1028 fSpacePointData[counter].fX = fCurrentRow;
1029 fSpacePointData[counter].fY = fpad;
1030 fSpacePointData[counter].fZ = ftime;
1033 fSpacePointData[counter].fCharge = list[j].fTotalCharge;
1034 fSpacePointData[counter].fPadRow = fCurrentRow;
1035 fSpacePointData[counter].fSigmaY2 = fpad2;
1036 fSpacePointData[counter].fSigmaZ2 = ftime2;
1038 fSpacePointData[counter].fMaxQ = list[j].fQMax;
1040 fSpacePointData[counter].fUsed = kFALSE; // only used / set in AliHLTTPCDisplay
1041 fSpacePointData[counter].fTrackN = -1; // only used / set in AliHLTTPCDisplay
1043 Int_t patch=fCurrentPatch;
1044 if(patch==-1) patch=0; //never store negative patch number
1045 fSpacePointData[counter].fID = counter
1046 +((fCurrentSlice&0x7f)<<25)+((patch&0x7)<<22);//Uli
1050 GetTrackID((Int_t)rint(fpad),(Int_t)rint(ftime),trackID);
1052 fSpacePointData[counter].fTrackID[0] = trackID[0];
1053 fSpacePointData[counter].fTrackID[1] = trackID[1];
1054 fSpacePointData[counter].fTrackID[2] = trackID[2];