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(){
85 // see header file for class documentation
88 if(fVectorInitialized){
89 DeInitializePadArray();
91 if(fNumberOfPadsInRow){
92 delete [] fNumberOfPadsInRow;
93 fNumberOfPadsInRow=NULL;
97 void AliHLTTPCClusterFinder::InitSlice(Int_t slice,Int_t patch,Int_t nmaxpoints){
98 // see header file for class documentation
102 fMaxNClusters = nmaxpoints;
103 fCurrentSlice = slice;
104 fCurrentPatch = patch;
105 fFirstRow=AliHLTTPCTransform::GetFirstRow(patch);
106 fLastRow=AliHLTTPCTransform::GetLastRow(patch);
109 void AliHLTTPCClusterFinder::InitializePadArray(){
110 // see header file for class documentation
112 if(fCurrentPatch>5||fCurrentPatch<0){
113 HLTFatal("Patch is not set");
117 HLTDebug("Patch number=%d",fCurrentPatch);
119 fFirstRow = AliHLTTPCTransform::GetFirstRow(fCurrentPatch);
120 fLastRow = AliHLTTPCTransform::GetLastRow(fCurrentPatch);
122 fNumberOfRows=fLastRow-fFirstRow+1;
123 fNumberOfPadsInRow= new UInt_t[fNumberOfRows];
125 memset( fNumberOfPadsInRow, 0, sizeof(Int_t)*(fNumberOfRows));
127 for(UInt_t i=0;i<fNumberOfRows;i++){
128 fNumberOfPadsInRow[i]=AliHLTTPCTransform::GetNPads(i+fFirstRow);
129 AliHLTTPCPadVector tmpRow;
130 for(UInt_t j=0;j<=fNumberOfPadsInRow[i];j++){
131 AliHLTTPCPad *tmpPad = new AliHLTTPCPad(2);
133 tmpRow.push_back(tmpPad);
135 fRowPadVector.push_back(tmpRow);
137 fVectorInitialized=kTRUE;
140 Int_t AliHLTTPCClusterFinder::DeInitializePadArray(){
141 // see header file for class documentation
143 for(UInt_t i=0;i<fNumberOfRows;i++){
144 for(UInt_t j=0;j<=fNumberOfPadsInRow[i];j++){
145 delete fRowPadVector[i][j];
146 fRowPadVector[i][j]=NULL;
148 fRowPadVector[i].clear();
150 fRowPadVector.clear();
156 void AliHLTTPCClusterFinder::SetOutputArray(AliHLTTPCSpacePointData *pt){
157 // see header file for class documentation
158 //set pointer to output
159 fSpacePointData = pt;
163 void AliHLTTPCClusterFinder::ReadDataUnsorted(void* ptr,unsigned long size){
164 // see header file for class documentation
166 fPtr = (UChar_t*)ptr;
169 if(!fVectorInitialized){
170 InitializePadArray();
173 if (fDigitReader->InitBlock(fPtr,fSize,fFirstRow,fLastRow,fCurrentPatch,fCurrentSlice)<0) {
174 HLTError("failed setting up digit reader (InitBlock)");
178 while(fDigitReader->NextChannel()){
179 UInt_t row=fDigitReader->GetRow();
180 UInt_t pad=fDigitReader->GetPad();
182 if(row>=fRowPadVector.size()){
183 HLTError("Row number is to large: %d, max is %d",row,fRowPadVector.size()-1);
186 if(pad>=fRowPadVector[row].size()){
187 HLTError("Pad number is to large: %d, max is %d",pad,fRowPadVector[row].size());
191 while(fDigitReader->NextBunch()){
192 if(fDigitReader->GetBunchSize()>1){//to remove single timebin values, this will have to change at some point
193 UInt_t time = fDigitReader->GetTime();
194 if((Int_t)time>=fFirstTimeBin && (Int_t)time+fDigitReader->GetBunchSize()<=fLastTimeBin){
195 const UInt_t *bunchData= fDigitReader->GetSignals();
196 AliHLTTPCClusters candidate;
197 for(Int_t i=0;i<fDigitReader->GetBunchSize();i++){
198 candidate.fTotalCharge+=bunchData[i];
199 candidate.fTime += time*bunchData[i];
200 candidate.fTime2 += time*time*bunchData[i];
201 if(bunchData[i]>candidate.fQMax){
202 candidate.fQMax=bunchData[i];
206 if(candidate.fTotalCharge>0){
207 candidate.fMean=candidate.fTime/candidate.fTotalCharge;
208 candidate.fPad=candidate.fTotalCharge*pad;
209 candidate.fPad2=candidate.fPad*pad;
210 candidate.fLastMergedPad=pad;
211 candidate.fRowNumber=row+fDigitReader->GetRowOffset();
213 if(fRowPadVector[row][pad] != NULL){
214 fRowPadVector[row][pad]->AddClusterCandidate(candidate);
222 void AliHLTTPCClusterFinder::ReadDataUnsortedDeconvoluteTime(void* ptr,unsigned long size){
223 // see header file for class documentation
226 fPtr = (UChar_t*)ptr;
229 if(!fVectorInitialized){
230 InitializePadArray();
233 if (fDigitReader->InitBlock(fPtr,fSize,fFirstRow,fLastRow,fCurrentPatch,fCurrentSlice)<0) {
234 HLTError("failed setting up digit reader (InitBlock)");
238 while(fDigitReader->NextChannel()){
239 UInt_t row=fDigitReader->GetRow();
240 UInt_t pad=fDigitReader->GetPad();
242 while(fDigitReader->NextBunch()){
243 if(fDigitReader->GetBunchSize()>1){//to remove single timebin values, this will have to change at some point
244 UInt_t time = fDigitReader->GetTime();
245 if((Int_t)time>=fFirstTimeBin && (Int_t)time+fDigitReader->GetBunchSize()<=fLastTimeBin){
246 Int_t indexInBunchData=0;
247 Bool_t moreDataInBunch=kFALSE;
249 Bool_t signalFalling=kFALSE;
250 const UInt_t *bunchData= fDigitReader->GetSignals();
252 AliHLTTPCClusters candidate;
253 for(Int_t i=indexInBunchData;i<fDigitReader->GetBunchSize();i++){
254 // Checks if one need to deconvolute the signals
255 if(bunchData[i]>prevSignal && signalFalling==kTRUE){
256 if(i<fDigitReader->GetBunchSize()-1){ // means there are more than one signal left in the bunch
257 moreDataInBunch=kTRUE;
263 // Checks if the signal is 0, then quit processing the data.
264 if(bunchData[i]==0 && i<fDigitReader->GetBunchSize()-1){//means we have 0 data fom the rcu, might happen depending on the configuration settings
265 moreDataInBunch=kTRUE;
270 if(prevSignal>bunchData[i]){//means the peak of the signal has been reached and deconvolution will happen if the signal rise again.
273 candidate.fTotalCharge+=bunchData[i];
274 candidate.fTime += time*bunchData[i];
275 candidate.fTime2 += time*time*bunchData[i];
276 if(bunchData[i]>candidate.fQMax){
277 candidate.fQMax=bunchData[i];
280 prevSignal=bunchData[i];
284 if(candidate.fTotalCharge>0){
285 candidate.fMean=candidate.fTime/candidate.fTotalCharge;
286 candidate.fPad=candidate.fTotalCharge*pad;
287 candidate.fPad2=candidate.fPad*pad;
288 candidate.fLastMergedPad=pad;
289 candidate.fRowNumber=row+fDigitReader->GetRowOffset();
291 fRowPadVector[row][pad]->AddClusterCandidate(candidate);
292 if(indexInBunchData<fDigitReader->GetBunchSize()-1){
293 moreDataInBunch=kFALSE;
295 }while(moreDataInBunch);
302 Bool_t AliHLTTPCClusterFinder::ComparePads(AliHLTTPCPad *nextPad,AliHLTTPCClusters* cluster,Int_t nextPadToRead){
303 // see header file for class documentation
305 //Checking if we have a match on the next pad
306 for(UInt_t candidateNumber=0;candidateNumber<nextPad->fClusterCandidates.size();candidateNumber++){
307 AliHLTTPCClusters *candidate =&nextPad->fClusterCandidates[candidateNumber];
308 if(cluster->fMean-candidate->fMean==1 || candidate->fMean-cluster->fMean==1 || cluster->fMean-candidate->fMean==0){
310 if(candidate->fTotalCharge<fTotalChargeOfPreviousClusterCandidate){//peak is reached
311 fChargeOfCandidatesFalling=kTRUE;
313 if(candidate->fTotalCharge>fTotalChargeOfPreviousClusterCandidate && fChargeOfCandidatesFalling==kTRUE){//we have deconvolution
317 cluster->fMean=candidate->fMean;
318 cluster->fTotalCharge+=candidate->fTotalCharge;
319 cluster->fTime += candidate->fTime;
320 cluster->fTime2 += candidate->fTime2;
321 cluster->fPad+=candidate->fPad;
322 cluster->fPad2+=candidate->fPad2;
323 cluster->fLastMergedPad=candidate->fPad;
324 if(candidate->fQMax>cluster->fQMax){
325 cluster->fQMax=candidate->fQMax;
329 UInt_t rowNo = nextPad->GetRowNumber();
330 UInt_t padNo = nextPad->GetPadNumber();
332 fRowPadVector[rowNo][padNo-2]->fSelectedPad=kTRUE;
333 fRowPadVector[rowNo][padNo-2]->fHWAddress=(AliHLTUInt16_t)fDigitReader->GetAltroBlockHWaddr(rowNo,padNo-2);
335 fRowPadVector[rowNo][padNo-1]->fSelectedPad=kTRUE;// quick solution to set the first pad to selected
336 fRowPadVector[rowNo][padNo-1]->fHWAddress=(AliHLTUInt16_t)fDigitReader->GetAltroBlockHWaddr(rowNo,padNo-1);
337 fRowPadVector[rowNo][padNo]->fSelectedPad=kTRUE;
338 fRowPadVector[rowNo][padNo]->fHWAddress=(AliHLTUInt16_t)fDigitReader->GetAltroBlockHWaddr(rowNo,padNo);
341 //setting the matched pad to used
342 nextPad->fUsedClusterCandidates[candidateNumber]=1;
344 if(nextPadToRead<(Int_t)fNumberOfPadsInRow[fRowOfFirstCandidate]){
345 nextPad=fRowPadVector[fRowOfFirstCandidate][nextPadToRead];
346 ComparePads(nextPad,cluster,nextPadToRead);
359 Int_t AliHLTTPCClusterFinder::FillHWAddressList(AliHLTUInt16_t *hwaddlist, Int_t maxHWadd){
360 // see header file for class documentation
363 for(UInt_t row=0;row<fNumberOfRows;row++){
364 for(UInt_t pad=0;pad<fNumberOfPadsInRow[row]-1;pad++){
365 if(fRowPadVector[row][pad]->fSelectedPad){
366 if(counter<maxHWadd){
367 hwaddlist[counter]=(AliHLTUInt16_t)fRowPadVector[row][pad]->fHWAddress;
371 HLTWarning("To many hardwareaddresses, skip adding");
380 void AliHLTTPCClusterFinder::FindClusters(){
381 // see header file for function documentation
383 AliHLTTPCClusters* tmpCandidate=NULL;
384 for(UInt_t row=0;row<fNumberOfRows;row++){
385 fRowOfFirstCandidate=row;
386 for(UInt_t pad=0;pad<fNumberOfPadsInRow[row];pad++){
387 AliHLTTPCPad *tmpPad=fRowPadVector[row][pad];
388 for(size_t candidate=0;candidate<tmpPad->fClusterCandidates.size();candidate++){
389 if(tmpPad->fUsedClusterCandidates[candidate]){
392 tmpCandidate=&tmpPad->fClusterCandidates[candidate];
393 UInt_t tmpTotalCharge=tmpCandidate->fTotalCharge;
395 ComparePads(fRowPadVector[row][pad+1],tmpCandidate,pad+1);
396 if(tmpCandidate->fTotalCharge>tmpTotalCharge){
398 fClusters.push_back(*tmpCandidate);
401 tmpPad->ClearCandidates();
403 fRowPadVector[row][fNumberOfPadsInRow[row]]->ClearCandidates();
406 HLTInfo("Found %d clusters.",fClusters.size());
408 //TODO: Change so it stores AliHLTTPCSpacePointData directly, instead of this copying
410 AliClusterData * clusterlist = new AliClusterData[fClusters.size()]; //Clusterlist
411 for(unsigned int i=0;i<fClusters.size();i++){
412 clusterlist[i].fTotalCharge = fClusters[i].fTotalCharge;
413 clusterlist[i].fPad = fClusters[i].fPad;
414 clusterlist[i].fPad2 = fClusters[i].fPad2;
415 clusterlist[i].fTime = fClusters[i].fTime;
416 clusterlist[i].fTime2 = fClusters[i].fTime2;
417 clusterlist[i].fMean = fClusters[i].fMean;
418 clusterlist[i].fFlags = fClusters[i].fFlags;
419 clusterlist[i].fChargeFalling = fClusters[i].fChargeFalling;
420 clusterlist[i].fLastCharge = fClusters[i].fLastCharge;
421 clusterlist[i].fLastMergedPad = fClusters[i].fLastMergedPad;
422 clusterlist[i].fRow = fClusters[i].fRowNumber;
423 clusterlist[i].fQMax = fClusters[i].fQMax;
426 WriteClusters(fClusters.size(),clusterlist);
427 delete [] clusterlist;
432 //---------------------------------- Under this line the old sorted clusterfinder functions can be found --------------------------------
435 void AliHLTTPCClusterFinder::PrintClusters(){
436 // see header file for class documentation
438 for(size_t i=0;i<fClusters.size();i++){
439 HLTInfo("Cluster number: %d",i);
440 HLTInfo("Row: %d \t Pad: %d",fClusters[i].fRowNumber,fClusters[i].fPad/fClusters[i].fTotalCharge);
441 HLTInfo("Total Charge: %d",fClusters[i].fTotalCharge);
442 HLTInfo("fPad: %d",fClusters[i].fPad);
443 HLTInfo("PadError: %d",fClusters[i].fPad2);
444 HLTInfo("TimeMean: %d",fClusters[i].fTime/fClusters[i].fTotalCharge);
445 HLTInfo("TimeError: %d",fClusters[i].fTime2);
446 HLTInfo("EndOfCluster:");
450 void AliHLTTPCClusterFinder::Read(void* ptr,unsigned long size){
452 fPtr = (UChar_t*)ptr;
456 void AliHLTTPCClusterFinder::ProcessDigits(){
457 // see header file for class documentation
460 bool readValue = true;
463 UShort_t time=0,newTime=0;
464 UInt_t pad=0,newPad=0;
465 AliHLTTPCSignal_t charge=0;
469 // initialize block for reading packed data
470 iResult=fDigitReader->InitBlock(fPtr,fSize,fFirstRow,fLastRow,fCurrentPatch,fCurrentSlice);
471 if (iResult<0) return;
473 readValue = fDigitReader->Next();
475 // Matthias 08.11.2006 the following return would cause termination without writing the
476 // ClusterData and thus would block the component. I just want to have the commented line
477 // here for information
478 //if (!readValue)return;
480 pad = fDigitReader->GetPad();
481 time = fDigitReader->GetTime();
482 fCurrentRow = fDigitReader->GetRow();
484 if ( fCurrentPatch >= 2 ) // Outer sector, patches 2, 3, 4, 5
485 rowOffset = AliHLTTPCTransform::GetFirstRow( 2 );
487 fCurrentRow += rowOffset;
489 UInt_t lastpad = 123456789;
490 const UInt_t kPadArraySize=5000;
491 const UInt_t kClusterListSize=10000;
492 AliClusterData *pad1[kPadArraySize]; //2 lists for internal memory=2pads
493 AliClusterData *pad2[kPadArraySize]; //2 lists for internal memory=2pads
494 AliClusterData clusterlist[kClusterListSize]; //Clusterlist
496 AliClusterData **currentPt; //List of pointers to the current pad
497 AliClusterData **previousPt; //List of pointers to the previous pad
500 UInt_t nprevious=0,ncurrent=0,ntotal=0;
502 /* quick implementation of baseline calculation and zero suppression
503 open a pad object for each pad and delete it after processing.
504 later a list of pad objects with base line history can be used
505 The whole thing only works if we really get unprocessed raw data, if
506 the data is already zero suppressed, there might be gaps in the time
509 Int_t gatingGridOffset=50;
511 gatingGridOffset=fFirstTimeBin;
513 AliHLTTPCPad baseline(gatingGridOffset, AliHLTTPCTransform::GetNTimeBins());
514 // just to make later conversion to a list of objects easier
515 AliHLTTPCPad* pCurrentPad=NULL;
517 if (fSignalThreshold>=0) {
518 pCurrentPad=&baseline;
519 baseline.SetThreshold(fSignalThreshold);
522 while ( readValue!=0 && iResult>=0){ // Reads through all digits in block
529 if(currentPt == pad2){
537 nprevious = ncurrent;
539 if(pad != lastpad+1){
540 //this happens if there is a pad with no signal.
541 nprevious = ncurrent = 0;
546 Bool_t newcluster = kTRUE;
547 UInt_t seqcharge=0,seqaverage=0,seqerror=0;
548 AliHLTTPCSignal_t lastcharge=0;
549 UInt_t bLastWasFalling=0;
554 redo: //This is a goto.
565 while(iResult>=0){ //Loop over time bins of current pad
566 // read all the values for one pad at once to calculate the base line
568 if (!pCurrentPad->IsStarted()) {
569 //HLTDebug("reading data for pad %d, padrow %d", fDigitReader->GetPad(), fDigitReader->GetRow()+rowOffset);
570 pCurrentPad->SetID(fDigitReader->GetRow()+rowOffset,fDigitReader->GetPad());
571 if ((pCurrentPad->StartEvent())>=0) {
573 if ((fDigitReader->GetRow()+rowOffset)!=pCurrentPad->GetRowNumber()) break;
574 if (fDigitReader->GetPad()!=pCurrentPad->GetPadNumber()) break;
575 pCurrentPad->SetRawData(fDigitReader->GetTime(), fDigitReader->GetSignal());
576 //HLTDebug("set raw data to pad: bin %d charge %d", fDigitReader->GetTime(), fDigitReader->GetSignal());
577 } while ((readValue = fDigitReader->Next())!=0);
579 pCurrentPad->CalculateBaseLine(AliHLTTPCTransform::GetNTimeBins()/2);
580 if (pCurrentPad->Next(kTRUE/*do zero suppression*/)==0) {
581 //HLTDebug("no data available after zero suppression");
582 pCurrentPad->StopEvent();
583 pCurrentPad->ResetHistory();
586 time=pCurrentPad->GetCurrentPosition();
587 if (time>pCurrentPad->GetSize()) {
588 HLTError("invalid time bin for pad");
594 Float_t occupancy=pCurrentPad->GetOccupancy();
595 //HLTDebug("pad %d occupancy level: %f", pCurrentPad->GetPadNumber(), occupancy);
596 if ( occupancy < fOccupancyLimit ) {
597 charge = pCurrentPad->GetCorrectedData();
600 //HLTDebug("ignoring pad %d with occupancy level %f", pCurrentPad->GetPadNumber(), occupancy);
603 charge = fDigitReader->GetSignal();
605 //HLTDebug("get next charge value: position %d charge %d", time, charge);
609 if (fDigitReader->GetRow() == 90){
610 ///// LOG(AliHLTTPCLog::kFatal,"AliHLTTPCClusterFinder::Row","row90") << "PAD=" << fDigitReader->GetPad() << " TIME=" << fDigitReader->GetTime()
611 // << " SIGNAL=" << fDigitReader->GetSignal() << ENDLOG;
615 if(time >= AliHLTTPCTransform::GetNTimeBins()){
616 HLTWarning("Pad %d: Timebin (%d) out of range (%d)", pad, time, AliHLTTPCTransform::GetNTimeBins());
621 //Get the current ADC-value
624 //Check if the last pixel in the sequence is smaller than this
625 if(charge > lastcharge){
631 else bLastWasFalling = 1; //last pixel was larger than this
635 //Sum the total charge of this sequence
637 seqaverage += time*charge;
638 seqerror += time*time*charge;
642 if((pCurrentPad->Next(kTRUE/*do zero suppression*/))==0) {
643 pCurrentPad->StopEvent();
644 pCurrentPad->ResetHistory();
646 newPad = fDigitReader->GetPad();
647 newTime = fDigitReader->GetTime();
648 newRow = fDigitReader->GetRow() + rowOffset;
653 newPad=pCurrentPad->GetPadNumber();
654 newTime=pCurrentPad->GetCurrentPosition();
655 newRow=pCurrentPad->GetRowNumber();
657 readValue = fDigitReader->Next();
658 //Check where to stop:
659 if(!readValue) break; //No more value
661 newPad = fDigitReader->GetPad();
662 newTime = fDigitReader->GetTime();
663 newRow = fDigitReader->GetRow() + rowOffset;
666 if(newPad != pad)break; //new pad
667 if(newTime != time+1) break; //end of sequence
670 // pad = newpad; is equal
673 }//end loop over sequence
675 //HLTDebug("ended time bin sequence loop: seqcharge=%d readValue=%d", seqcharge, readValue);
676 //HLTDebug("pad=%d newpad=%d current row=%d newrow=%d", pad, newPad, fCurrentRow, newRow);
678 // with active zero suppression zero values are possible
682 //Calculate mean of sequence:
685 seqmean = seqaverage/seqcharge;
687 LOG(AliHLTTPCLog::kFatal,"AliHLTTPCClusterFinder::ProcessRow","Data")
688 <<"Error in data given to the cluster finder"<<ENDLOG;
693 //Calculate mean in pad direction:
694 Int_t padmean = seqcharge*pad;
695 Int_t paderror = pad*padmean;
697 //Compare with results on previous pad:
698 for(UInt_t p=0; p<nprevious && p<kPadArraySize && ncurrent<kPadArraySize; p++){
700 //dont merge sequences on the same pad twice
701 if(previousPt[p]->fLastMergedPad==pad) continue;
703 Int_t difference = seqmean - previousPt[p]->fMean;
704 if(difference < -fMatch) break;
706 if(difference <= fMatch){ //There is a match here!!
707 AliClusterData *local = previousPt[p];
710 if(seqcharge > local->fLastCharge){
711 if(local->fChargeFalling){ //The previous pad was falling
712 break; //create a new cluster
715 else local->fChargeFalling = 1;
716 local->fLastCharge = seqcharge;
719 //Don't create a new cluster, because we found a match
722 //Update cluster on current pad with the matching one:
723 local->fTotalCharge += seqcharge;
724 local->fPad += padmean;
725 local->fPad2 += paderror;
726 local->fTime += seqaverage;
727 local->fTime2 += seqerror;
728 local->fMean = seqmean;
729 local->fFlags++; //means we have more than one pad
730 local->fLastMergedPad = pad;
732 currentPt[ncurrent] = local;
736 } //Checking for match at previous pad
737 } //Loop over results on previous pad.
739 if(newcluster && ncurrent<kPadArraySize){
740 //Start a new cluster. Add it to the clusterlist, and update
741 //the list of pointers to clusters in current pad.
742 //current pad will be previous pad on next pad.
744 //Add to the clusterlist:
745 AliClusterData *tmp = &clusterlist[ntotal];
746 tmp->fTotalCharge = seqcharge;
748 tmp->fPad2 = paderror;
749 tmp->fTime = seqaverage;
750 tmp->fTime2 = seqerror;
751 tmp->fMean = seqmean;
752 tmp->fFlags = 0; //flags for single pad clusters
753 tmp->fLastMergedPad = pad;
756 tmp->fChargeFalling = 0;
757 tmp->fLastCharge = seqcharge;
760 //Update list of pointers to previous pad:
761 currentPt[ncurrent] = &clusterlist[ntotal];
767 if(newbin >= 0) goto redo;
769 // to prevent endless loop
770 if(time >= AliHLTTPCTransform::GetNTimeBins()){
771 HLTWarning("Timebin (%d) out of range (%d)", time, AliHLTTPCTransform::GetNTimeBins());
776 if(!readValue) break; //No more value
778 if (ntotal>=kClusterListSize || ncurrent>=kPadArraySize) {
779 HLTWarning("pad array size exceeded ntotal=%d ncurrent=%d, skip rest of the data", ntotal, ncurrent);
783 if(fCurrentRow != newRow){
784 WriteClusters(ntotal,clusterlist);
794 fCurrentRow = newRow;
800 } // END while(readValue)
802 WriteClusters(ntotal,clusterlist);
804 HLTInfo("ClusterFinder found %d clusters in slice %d patch %d", fNClusters, fCurrentSlice, fCurrentPatch);
808 void AliHLTTPCClusterFinder::WriteClusters(Int_t nclusters,AliClusterData *list){
809 // see header file for class documentation
811 //write cluster to output pointer
812 Int_t thisrow=-1,thissector=-1;
813 UInt_t counter = fNClusters;
815 for(int j=0; j<nclusters; j++)
820 if(!list[j].fFlags) continue; //discard single pad clusters
821 if(list[j].fTotalCharge < fThreshold) continue; //noise cluster
824 Float_t fpad =(Float_t)list[j].fPad / list[j].fTotalCharge;
825 Float_t fpad2=fXYErr*fXYErr; //fixed given error
826 Float_t ftime =(Float_t)list[j].fTime / list[j].fTotalCharge;
827 Float_t ftime2=fZErr*fZErr; //fixed given error
832 fCurrentRow=list[j].fRow;
836 if(fCalcerr) { //calc the errors, otherwice take the fixed error
837 Int_t patch = AliHLTTPCTransform::GetPatch(fCurrentRow);
838 UInt_t q2=list[j].fTotalCharge*list[j].fTotalCharge;
839 // Float_t sy2=list[j].fPad2 * list[j].fTotalCharge - list[j].fPad * list[j].fPad;
840 Float_t sy2=(Float_t)list[j].fPad2 * list[j].fTotalCharge - (Float_t)list[j].fPad * list[j].fPad;
843 LOG(AliHLTTPCLog::kError,"AliHLTTPCClusterFinder::WriteClusters","Cluster width")
844 <<"SigmaY2 negative "<<sy2<<" on row "<<fCurrentRow<<" "<<fpad<<" "<<ftime<<ENDLOG;
848 fpad2 = (sy2 + 1./12)*AliHLTTPCTransform::GetPadPitchWidth(patch)*AliHLTTPCTransform::GetPadPitchWidth(patch);
850 fpad2*=0.108; //constants are from offline studies
854 } else fpad2=sy2; //take the width not the error
856 // Float_t sz2=list[j].fTime2*list[j].fTotalCharge - list[j].fTime*list[j].fTime;
857 Float_t sz2=(Float_t)list[j].fTime2*list[j].fTotalCharge - (Float_t)list[j].fTime*list[j].fTime;
860 LOG(AliHLTTPCLog::kError,"AliHLTTPCClusterFinder::WriteClusters","Cluster width")
861 <<"SigmaZ2 negative "<<sz2<<" on row "<<fCurrentRow<<" "<<fpad<<" "<<ftime<<ENDLOG;
865 ftime2 = (sz2 + 1./12)*AliHLTTPCTransform::GetZWidth()*AliHLTTPCTransform::GetZWidth();
867 ftime2 *= 0.169; //constants are from offline studies
871 } else ftime2=sz2; //take the width, not the error
875 HLTInfo("WriteCluster: padrow %d pad %d +- %d time +- %d charge %d",fCurrentRow, fpad, fpad2, ftime, ftime2, list[j].fTotalCharge);
878 AliHLTTPCTransform::Slice2Sector(fCurrentSlice,fCurrentRow,thissector,thisrow);
879 AliHLTTPCTransform::Raw2Local(xyz,thissector,thisrow,fpad,ftime);
881 if(xyz[0]==0) LOG(AliHLTTPCLog::kError,"AliHLTTPCClustFinder","Cluster Finder")
882 <<AliHLTTPCLog::kDec<<"Zero cluster"<<ENDLOG;
883 if(fNClusters >= fMaxNClusters)
885 LOG(AliHLTTPCLog::kError,"AliHLTTPCClustFinder::WriteClusters","Cluster Finder")
886 <<AliHLTTPCLog::kDec<<"Too many clusters "<<fNClusters<<ENDLOG;
890 fSpacePointData[counter].fX = xyz[0];
891 // fSpacePointData[counter].fY = xyz[1];
892 if(fCurrentSlice<18){
893 fSpacePointData[counter].fY = xyz[1];
896 fSpacePointData[counter].fY = -1*xyz[1];
898 fSpacePointData[counter].fZ = xyz[2];
901 fSpacePointData[counter].fX = fCurrentRow;
902 fSpacePointData[counter].fY = fpad;
903 fSpacePointData[counter].fZ = ftime;
906 fSpacePointData[counter].fCharge = list[j].fTotalCharge;
907 fSpacePointData[counter].fPadRow = fCurrentRow;
908 fSpacePointData[counter].fSigmaY2 = fpad2;
909 fSpacePointData[counter].fSigmaZ2 = ftime2;
911 fSpacePointData[counter].fQMax = list[j].fQMax;
913 fSpacePointData[counter].fUsed = kFALSE; // only used / set in AliHLTTPCDisplay
914 fSpacePointData[counter].fTrackN = -1; // only used / set in AliHLTTPCDisplay
916 Int_t patch=fCurrentPatch;
917 if(patch==-1) patch=0; //never store negative patch number
918 fSpacePointData[counter].fID = counter
919 +((fCurrentSlice&0x7f)<<25)+((patch&0x7)<<22);//Uli
923 GetTrackID((Int_t)rint(fpad),(Int_t)rint(ftime),trackID);
925 fSpacePointData[counter].fTrackID[0] = trackID[0];
926 fSpacePointData[counter].fTrackID[1] = trackID[1];
927 fSpacePointData[counter].fTrackID[2] = trackID[2];
936 // STILL TO FIX ----------------------------------------------------------------------------
939 void AliHLTTPCClusterFinder::GetTrackID(Int_t pad,Int_t time,Int_t *trackID){
940 // see header file for class documentation
943 AliHLTTPCDigitRowData *rowPt = (AliHLTTPCDigitRowData*)fDigitRowData;
945 trackID[0]=trackID[1]=trackID[2]=-2;
946 for(Int_t i=fFirstRow; i<=fLastRow; i++){
947 if(rowPt->fRow < (UInt_t)fCurrentRow){
948 AliHLTTPCMemHandler::UpdateRowPointer(rowPt);
951 AliHLTTPCDigitData *digPt = (AliHLTTPCDigitData*)rowPt->fDigitData;
952 for(UInt_t j=0; j<rowPt->fNDigit; j++){
953 Int_t cpad = digPt[j].fPad;
954 Int_t ctime = digPt[j].fTime;
955 if(cpad != pad) continue;
956 if(ctime != time) continue;
958 trackID[0] = digPt[j].fTrackID[0];
959 trackID[1] = digPt[j].fTrackID[1];
960 trackID[2] = digPt[j].fTrackID[2];
971 void AliHLTTPCClusterFinder::WriteClusters(Int_t nclusters,AliHLTTPCClusters *list){//This is used when using the AliHLTTPCClusters class for cluster data
972 // see header file for class documentation
974 //write cluster to output pointer
975 Int_t thisrow,thissector;
976 UInt_t counter = fNClusters;
978 for(int j=0; j<nclusters; j++)
980 if(!list[j].fFlags) continue; //discard single pad clusters
981 if(list[j].fTotalCharge < fThreshold) continue; //noise cluster
984 Float_t fpad =(Float_t)list[j].fPad / list[j].fTotalCharge;
985 Float_t fpad2=fXYErr*fXYErr; //fixed given error
986 Float_t ftime =(Float_t)list[j].fTime / list[j].fTotalCharge;
987 Float_t ftime2=fZErr*fZErr; //fixed given error
990 if(fCalcerr) { //calc the errors, otherwice take the fixed error
991 Int_t patch = AliHLTTPCTransform::GetPatch(fCurrentRow);
992 UInt_t q2=list[j].fTotalCharge*list[j].fTotalCharge;
993 Float_t sy2=list[j].fPad2 * list[j].fTotalCharge - list[j].fPad * list[j].fPad;
996 LOG(AliHLTTPCLog::kError,"AliHLTTPCClusterFinder::WriteClusters","Cluster width")
997 <<"SigmaY2 negative "<<sy2<<" on row "<<fCurrentRow<<" "<<fpad<<" "<<ftime<<ENDLOG;
1001 fpad2 = (sy2 + 1./12)*AliHLTTPCTransform::GetPadPitchWidth(patch)*AliHLTTPCTransform::GetPadPitchWidth(patch);
1003 fpad2*=0.108; //constants are from offline studies
1007 } else fpad2=sy2; //take the width not the error
1009 Float_t sz2=list[j].fTime2*list[j].fTotalCharge - list[j].fTime*list[j].fTime;
1012 LOG(AliHLTTPCLog::kError,"AliHLTTPCClusterFinder::WriteClusters","Cluster width")
1013 <<"SigmaZ2 negative "<<sz2<<" on row "<<fCurrentRow<<" "<<fpad<<" "<<ftime<<ENDLOG;
1017 ftime2 = (sz2 + 1./12)*AliHLTTPCTransform::GetZWidth()*AliHLTTPCTransform::GetZWidth();
1019 ftime2 *= 0.169; //constants are from offline studies
1023 } else ftime2=sz2; //take the width, not the error
1027 HLTInfo("WriteCluster: padrow %d pad %d +- %d time +- %d charge %d",fCurrentRow, fpad, fpad2, ftime, ftime2, list[j].fTotalCharge);
1030 AliHLTTPCTransform::Slice2Sector(fCurrentSlice,fCurrentRow,thissector,thisrow);
1031 AliHLTTPCTransform::Raw2Local(xyz,thissector,thisrow,fpad,ftime);
1033 if(xyz[0]==0) LOG(AliHLTTPCLog::kError,"AliHLTTPCClustFinder","Cluster Finder")
1034 <<AliHLTTPCLog::kDec<<"Zero cluster"<<ENDLOG;
1035 if(fNClusters >= fMaxNClusters)
1037 LOG(AliHLTTPCLog::kError,"AliHLTTPCClustFinder::WriteClusters","Cluster Finder")
1038 <<AliHLTTPCLog::kDec<<"Too many clusters "<<fNClusters<<ENDLOG;
1042 fSpacePointData[counter].fX = xyz[0];
1043 // fSpacePointData[counter].fY = xyz[1];
1044 if(fCurrentSlice<18){
1045 fSpacePointData[counter].fY = xyz[1];
1048 fSpacePointData[counter].fY = -1*xyz[1];
1050 fSpacePointData[counter].fZ = xyz[2];
1053 fSpacePointData[counter].fX = fCurrentRow;
1054 fSpacePointData[counter].fY = fpad;
1055 fSpacePointData[counter].fZ = ftime;
1058 fSpacePointData[counter].fCharge = list[j].fTotalCharge;
1059 fSpacePointData[counter].fPadRow = fCurrentRow;
1060 fSpacePointData[counter].fSigmaY2 = fpad2;
1061 fSpacePointData[counter].fSigmaZ2 = ftime2;
1063 fSpacePointData[counter].fQMax = list[j].fQMax;
1065 fSpacePointData[counter].fUsed = kFALSE; // only used / set in AliHLTTPCDisplay
1066 fSpacePointData[counter].fTrackN = -1; // only used / set in AliHLTTPCDisplay
1068 Int_t patch=fCurrentPatch;
1069 if(patch==-1) patch=0; //never store negative patch number
1070 fSpacePointData[counter].fID = counter
1071 +((fCurrentSlice&0x7f)<<25)+((patch&0x7)<<22);//Uli
1075 GetTrackID((Int_t)rint(fpad),(Int_t)rint(ftime),trackID);
1077 fSpacePointData[counter].fTrackID[0] = trackID[0];
1078 fSpacePointData[counter].fTrackID[1] = trackID[1];
1079 fSpacePointData[counter].fTrackID[2] = trackID[2];