]> git.uio.no Git - u/mrichter/AliRoot.git/blame - HLT/TPCLib/AliHLTTPCClusterFinder.cxx
code documantation and minor cleanup
[u/mrichter/AliRoot.git] / HLT / TPCLib / AliHLTTPCClusterFinder.cxx
CommitLineData
a38a7850 1// @(#) $Id$
4aa41877 2// Original: AliHLTClustFinderNew.cxx,v 1.29 2005/06/14 10:55:21 cvetan Exp
a38a7850 3
297174de 4//**************************************************************************
5//* This file is property of and copyright by the ALICE HLT Project *
6//* ALICE Experiment at CERN, All rights reserved. *
7//* *
8//* Primary Authors: Anders Vestbo, Constantin Loizides *
9//* Developers: Kenneth Aamodt <kenneth.aamodt@student.uib.no> *
10//* Kalliopi Kanaki *
11//* for The ALICE HLT Project. *
12//* *
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//**************************************************************************
a38a7850 21
600e6a1b 22/** @file AliHLTTPCClusterFinder.cxx
98034d0d 23 @author Kenneth Aamodt, Kalliopi Kanaki
600e6a1b 24 @date
25 @brief Cluster Finder for the TPC
26*/
a38a7850 27
28#include "AliHLTTPCDigitReader.h"
a38a7850 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"
46b33a24 36#include "AliHLTTPCPad.h"
8252a538 37#include <sys/time.h>
a38a7850 38
39#if __GNUC__ >= 3
40using namespace std;
41#endif
42
a38a7850 43ClassImp(AliHLTTPCClusterFinder)
44
45AliHLTTPCClusterFinder::AliHLTTPCClusterFinder()
46b33a24 46 :
2a083ac4 47 fSpacePointData(NULL),
48 fDigitReader(NULL),
49 fPtr(NULL),
50 fSize(0),
46b33a24 51 fDeconvTime(kTRUE),
2a083ac4 52 fDeconvPad(kTRUE),
46b33a24 53 fStdout(kFALSE),
54 fCalcerr(kTRUE),
55 fRawSP(kFALSE),
56 fFirstRow(0),
57 fLastRow(0),
2a083ac4 58 fCurrentRow(0),
59 fCurrentSlice(0),
60 fCurrentPatch(0),
61 fMatch(1),
62 fThreshold(10),
63 fSignalThreshold(-1),
64defa03 64 fNSigmaThreshold(0),
2a083ac4 65 fNClusters(0),
66 fMaxNClusters(0),
67 fXYErr(0.2),
68 fZErr(0.3),
01f43166 69 fOccupancyLimit(1.0),
64defa03 70 fUnsorted(0),
a74855c2 71 fVectorInitialized(kFALSE),
8252a538 72 fRowPadVector(),
73 fClusters(),
a74855c2 74 fNumberOfPadsInRow(NULL),
75 fNumberOfRows(0),
8252a538 76 fRowOfFirstCandidate(0)
a38a7850 77{
8252a538 78 //constructor
46b33a24 79}
a38a7850 80
a38a7850 81AliHLTTPCClusterFinder::~AliHLTTPCClusterFinder()
82{
83 //destructor
8252a538 84 if(fVectorInitialized){
85 DeInitializePadArray();
86 }
87 if(fNumberOfPadsInRow){
88 delete [] fNumberOfPadsInRow;
89 fNumberOfPadsInRow=NULL;
90 }
a38a7850 91}
92
93void AliHLTTPCClusterFinder::InitSlice(Int_t slice,Int_t patch,Int_t firstrow, Int_t lastrow,Int_t nmaxpoints)
94{
95 //init slice
96 fNClusters = 0;
97 fMaxNClusters = nmaxpoints;
98 fCurrentSlice = slice;
99 fCurrentPatch = patch;
100 fFirstRow = firstrow;
101 fLastRow = lastrow;
102}
103
8252a538 104void AliHLTTPCClusterFinder::InitializePadArray(){
105 // see header file for class documentation
106
107 if(fCurrentPatch>5||fCurrentPatch<0){
108 HLTFatal("Patch is not set");
109 return;
110 }
111
112 HLTDebug("Patch number=%d",fCurrentPatch);
113
114 fFirstRow = AliHLTTPCTransform::GetFirstRow(fCurrentPatch);
115 fLastRow = AliHLTTPCTransform::GetLastRow(fCurrentPatch);
116
117 fNumberOfRows=fLastRow-fFirstRow+1;
118 fNumberOfPadsInRow= new UInt_t[fNumberOfRows];
119
120 memset( fNumberOfPadsInRow, 0, sizeof(Int_t)*(fNumberOfRows));
121
a74855c2 122 for(UInt_t i=0;i<fNumberOfRows;i++){
8252a538 123 fNumberOfPadsInRow[i]=AliHLTTPCTransform::GetNPads(i+fFirstRow);
124 AliHLTTPCPadVector tmpRow;
a74855c2 125 for(UInt_t j=0;j<fNumberOfPadsInRow[i];j++){
8252a538 126 AliHLTTPCPad *tmpPad = new AliHLTTPCPad(2);
127 tmpPad->SetID(i,j);
128 tmpRow.push_back(tmpPad);
129 }
130 fRowPadVector.push_back(tmpRow);
131 }
132 fVectorInitialized=kTRUE;
133}
134
135Int_t AliHLTTPCClusterFinder::DeInitializePadArray()
136{
137 // see header file for class documentation
a74855c2 138 for(UInt_t i=0;i<fNumberOfRows;i++){
139 for(UInt_t j=0;j<fNumberOfPadsInRow[i];j++){
8252a538 140 delete fRowPadVector[i][j];
141 fRowPadVector[i][j]=NULL;
142 }
143 fRowPadVector[i].clear();
144 }
145 fRowPadVector.clear();
146 return 1;
147}
148
149
a38a7850 150void AliHLTTPCClusterFinder::InitSlice(Int_t slice,Int_t patch,Int_t nmaxpoints)
151{
152 //init slice
153 fNClusters = 0;
154 fMaxNClusters = nmaxpoints;
155 fCurrentSlice = slice;
156 fCurrentPatch = patch;
157 fFirstRow=AliHLTTPCTransform::GetFirstRow(patch);
158 fLastRow=AliHLTTPCTransform::GetLastRow(patch);
159}
160
161void AliHLTTPCClusterFinder::SetOutputArray(AliHLTTPCSpacePointData *pt)
162{
163 //set pointer to output
164 fSpacePointData = pt;
165}
166
167void AliHLTTPCClusterFinder::Read(void* ptr,unsigned long size){
168 //set input pointer
169 fPtr = (UChar_t*)ptr;
170 fSize = size;
171}
172
173void AliHLTTPCClusterFinder::ProcessDigits()
174{
6b0fdc0e 175 int iResult=0;
a38a7850 176 bool readValue = true;
177 Int_t newRow = 0;
178 Int_t rowOffset = 0;
46b33a24 179 UShort_t time=0,newTime=0;
180 UInt_t pad=0,newPad=0;
181 AliHLTTPCSignal_t charge=0;
a38a7850 182
183 fNClusters = 0;
184
185 // initialize block for reading packed data
67fada6b 186 iResult=fDigitReader->InitBlock(fPtr,fSize,fFirstRow,fLastRow,fCurrentPatch,fCurrentSlice);
187 if (iResult<0) return;
188
a38a7850 189 readValue = fDigitReader->Next();
190
5235c3e9 191 // Matthias 08.11.2006 the following return would cause termination without writing the
6c1a9d9e 192 // ClusterData and thus would block the component. I just want to have the commented line
5235c3e9 193 // here for information
194 //if (!readValue)return;
db16520a 195
a38a7850 196 pad = fDigitReader->GetPad();
197 time = fDigitReader->GetTime();
198 fCurrentRow = fDigitReader->GetRow();
199
200 if ( fCurrentPatch >= 2 ) // Outer sector, patches 2, 3, 4, 5
201 rowOffset = AliHLTTPCTransform::GetFirstRow( 2 );
202
203 fCurrentRow += rowOffset;
204
205 UInt_t lastpad = 123456789;
2a083ac4 206 const UInt_t kPadArraySize=5000;
207 const UInt_t kClusterListSize=10000;
84645eb0 208 AliClusterData *pad1[kPadArraySize]; //2 lists for internal memory=2pads
209 AliClusterData *pad2[kPadArraySize]; //2 lists for internal memory=2pads
210 AliClusterData clusterlist[kClusterListSize]; //Clusterlist
a38a7850 211
212 AliClusterData **currentPt; //List of pointers to the current pad
213 AliClusterData **previousPt; //List of pointers to the previous pad
214 currentPt = pad2;
215 previousPt = pad1;
216 UInt_t nprevious=0,ncurrent=0,ntotal=0;
217
46b33a24 218 /* quick implementation of baseline calculation and zero suppression
219 open a pad object for each pad and delete it after processing.
220 later a list of pad objects with base line history can be used
221 The whole thing only works if we really get unprocessed raw data, if
222 the data is already zero suppressed, there might be gaps in the time
223 bins.
224 */
225 Int_t gatingGridOffset=50;
226 AliHLTTPCPad baseline(gatingGridOffset, AliHLTTPCTransform::GetNTimeBins());
227 // just to make later conversion to a list of objects easier
84645eb0 228 AliHLTTPCPad* pCurrentPad=NULL;
229 if (fSignalThreshold>=0) {
230 pCurrentPad=&baseline;
231 baseline.SetThreshold(fSignalThreshold);
232 }
46b33a24 233
6b0fdc0e 234 while ( readValue!=0 && iResult>=0){ // Reads through all digits in block
235 iResult=0;
a38a7850 236
237 if(pad != lastpad){
238 //This is a new pad
239
240 //Switch the lists:
241 if(currentPt == pad2){
242 currentPt = pad1;
243 previousPt = pad2;
244 }
245 else {
246 currentPt = pad2;
247 previousPt = pad1;
248 }
249 nprevious = ncurrent;
250 ncurrent = 0;
251 if(pad != lastpad+1){
252 //this happens if there is a pad with no signal.
253 nprevious = ncurrent = 0;
254 }
255 lastpad = pad;
256 }
257
258 Bool_t newcluster = kTRUE;
259 UInt_t seqcharge=0,seqaverage=0,seqerror=0;
2a083ac4 260 AliHLTTPCSignal_t lastcharge=0;
261 UInt_t bLastWasFalling=0;
a38a7850 262 Int_t newbin=-1;
263
264
265 if(fDeconvTime){
266 redo: //This is a goto.
267
268 if(newbin > -1){
269 //bin = newbin;
270 newbin = -1;
271 }
272
273 lastcharge=0;
2a083ac4 274 bLastWasFalling = 0;
a38a7850 275 }
276
6b0fdc0e 277 while(iResult>=0){ //Loop over time bins of current pad
46b33a24 278 // read all the values for one pad at once to calculate the base line
279 if (pCurrentPad) {
280 if (!pCurrentPad->IsStarted()) {
281 //HLTDebug("reading data for pad %d, padrow %d", fDigitReader->GetPad(), fDigitReader->GetRow()+rowOffset);
282 pCurrentPad->SetID(fDigitReader->GetRow()+rowOffset,fDigitReader->GetPad());
283 if ((pCurrentPad->StartEvent())>=0) {
284 do {
285 if ((fDigitReader->GetRow()+rowOffset)!=pCurrentPad->GetRowNumber()) break;
286 if (fDigitReader->GetPad()!=pCurrentPad->GetPadNumber()) break;
287 pCurrentPad->SetRawData(fDigitReader->GetTime(), fDigitReader->GetSignal());
288 //HLTDebug("set raw data to pad: bin %d charge %d", fDigitReader->GetTime(), fDigitReader->GetSignal());
289 } while ((readValue = fDigitReader->Next())!=0);
290 }
291 pCurrentPad->CalculateBaseLine(AliHLTTPCTransform::GetNTimeBins()/2);
292 if (pCurrentPad->Next(kTRUE/*do zero suppression*/)==0) {
84645eb0 293 //HLTDebug("no data available after zero suppression");
46b33a24 294 pCurrentPad->StopEvent();
295 pCurrentPad->ResetHistory();
296 break;
297 }
298 time=pCurrentPad->GetCurrentPosition();
299 if (time>pCurrentPad->GetSize()) {
300 HLTError("invalid time bin for pad");
301 break;
302 }
303 }
304 }
46b33a24 305 if (pCurrentPad) {
5235c3e9 306 Float_t occupancy=pCurrentPad->GetOccupancy();
307 //HLTDebug("pad %d occupancy level: %f", pCurrentPad->GetPadNumber(), occupancy);
308 if ( occupancy < fOccupancyLimit ) {
309 charge = pCurrentPad->GetCorrectedData();
310 } else {
311 charge = 0;
312 //HLTDebug("ignoring pad %d with occupancy level %f", pCurrentPad->GetPadNumber(), occupancy);
313 }
46b33a24 314 } else {
5235c3e9 315 charge = fDigitReader->GetSignal();
46b33a24 316 }
317 //HLTDebug("get next charge value: position %d charge %d", time, charge);
a38a7850 318
738c049f 319
320 // CHARGE DEBUG
321 if (fDigitReader->GetRow() == 90){
322///// LOG(AliHLTTPCLog::kFatal,"AliHLTTPCClusterFinder::Row","row90") << "PAD=" << fDigitReader->GetPad() << " TIME=" << fDigitReader->GetTime()
323 // << " SIGNAL=" << fDigitReader->GetSignal() << ENDLOG;
324
325 }
326
a38a7850 327 if(time >= AliHLTTPCTransform::GetNTimeBins()){
6b0fdc0e 328 HLTWarning("Pad %d: Timebin (%d) out of range (%d)", pad, time, AliHLTTPCTransform::GetNTimeBins());
329 iResult=-ERANGE;
a38a7850 330 }
46b33a24 331
332
a38a7850 333 //Get the current ADC-value
334 if(fDeconvTime){
335
336 //Check if the last pixel in the sequence is smaller than this
337 if(charge > lastcharge){
2a083ac4 338 if(bLastWasFalling){
a38a7850 339 newbin = 1;
340 break;
341 }
342 }
2a083ac4 343 else bLastWasFalling = 1; //last pixel was larger than this
a38a7850 344 lastcharge = charge;
345 }
346
347 //Sum the total charge of this sequence
348 seqcharge += charge;
349 seqaverage += time*charge;
350 seqerror += time*time*charge;
351
46b33a24 352 if (pCurrentPad) {
353
354 if((pCurrentPad->Next(kTRUE/*do zero suppression*/))==0) {
355 pCurrentPad->StopEvent();
356 pCurrentPad->ResetHistory();
357 if(readValue) {
358 newPad = fDigitReader->GetPad();
359 newTime = fDigitReader->GetTime();
360 newRow = fDigitReader->GetRow() + rowOffset;
361 }
362 break;
363 }
364
365 newPad=pCurrentPad->GetPadNumber();
366 newTime=pCurrentPad->GetCurrentPosition();
367 newRow=pCurrentPad->GetRowNumber();
368 } else {
a38a7850 369 readValue = fDigitReader->Next();
a38a7850 370 //Check where to stop:
371 if(!readValue) break; //No more value
372
373 newPad = fDigitReader->GetPad();
374 newTime = fDigitReader->GetTime();
375 newRow = fDigitReader->GetRow() + rowOffset;
46b33a24 376 }
a38a7850 377
378 if(newPad != pad)break; //new pad
379 if(newTime != time+1) break; //end of sequence
6b0fdc0e 380 if(iResult<0) break;
a38a7850 381
382 // pad = newpad; is equal
383 time = newTime;
384
385 }//end loop over sequence
386
46b33a24 387 //HLTDebug("ended time bin sequence loop: seqcharge=%d readValue=%d", seqcharge, readValue);
388 //HLTDebug("pad=%d newpad=%d current row=%d newrow=%d", pad, newPad, fCurrentRow, newRow);
389 if (seqcharge<=0) {
390 // with active zero suppression zero values are possible
391 continue;
392 }
a38a7850 393
394 //Calculate mean of sequence:
395 Int_t seqmean=0;
396 if(seqcharge)
397 seqmean = seqaverage/seqcharge;
398 else{
399 LOG(AliHLTTPCLog::kFatal,"AliHLTTPCClusterFinder::ProcessRow","Data")
400 <<"Error in data given to the cluster finder"<<ENDLOG;
401 seqmean = 1;
402 seqcharge = 1;
403 }
404
405 //Calculate mean in pad direction:
406 Int_t padmean = seqcharge*pad;
407 Int_t paderror = pad*padmean;
408
a38a7850 409 //Compare with results on previous pad:
84645eb0 410 for(UInt_t p=0; p<nprevious && p<kPadArraySize && ncurrent<kPadArraySize; p++){
a38a7850 411
412 //dont merge sequences on the same pad twice
413 if(previousPt[p]->fLastMergedPad==pad) continue;
414
415 Int_t difference = seqmean - previousPt[p]->fMean;
416 if(difference < -fMatch) break;
417
418 if(difference <= fMatch){ //There is a match here!!
419 AliClusterData *local = previousPt[p];
420
421 if(fDeconvPad){
422 if(seqcharge > local->fLastCharge){
423 if(local->fChargeFalling){ //The previous pad was falling
424 break; //create a new cluster
425 }
426 }
427 else local->fChargeFalling = 1;
428 local->fLastCharge = seqcharge;
429 }
430
431 //Don't create a new cluster, because we found a match
432 newcluster = kFALSE;
433
434 //Update cluster on current pad with the matching one:
435 local->fTotalCharge += seqcharge;
436 local->fPad += padmean;
437 local->fPad2 += paderror;
438 local->fTime += seqaverage;
439 local->fTime2 += seqerror;
440 local->fMean = seqmean;
441 local->fFlags++; //means we have more than one pad
442 local->fLastMergedPad = pad;
443
444 currentPt[ncurrent] = local;
445 ncurrent++;
446
447 break;
448 } //Checking for match at previous pad
449 } //Loop over results on previous pad.
450
84645eb0 451 if(newcluster && ncurrent<kPadArraySize){
a38a7850 452 //Start a new cluster. Add it to the clusterlist, and update
453 //the list of pointers to clusters in current pad.
454 //current pad will be previous pad on next pad.
455
456 //Add to the clusterlist:
457 AliClusterData *tmp = &clusterlist[ntotal];
458 tmp->fTotalCharge = seqcharge;
459 tmp->fPad = padmean;
460 tmp->fPad2 = paderror;
461 tmp->fTime = seqaverage;
462 tmp->fTime2 = seqerror;
463 tmp->fMean = seqmean;
464 tmp->fFlags = 0; //flags for single pad clusters
465 tmp->fLastMergedPad = pad;
466
467 if(fDeconvPad){
468 tmp->fChargeFalling = 0;
469 tmp->fLastCharge = seqcharge;
470 }
471
472 //Update list of pointers to previous pad:
473 currentPt[ncurrent] = &clusterlist[ntotal];
474 ntotal++;
475 ncurrent++;
476 }
477
478 if(fDeconvTime)
479 if(newbin >= 0) goto redo;
480
481 // to prevent endless loop
482 if(time >= AliHLTTPCTransform::GetNTimeBins()){
46b33a24 483 HLTWarning("Timebin (%d) out of range (%d)", time, AliHLTTPCTransform::GetNTimeBins());
a38a7850 484 break;
485 }
486
487
488 if(!readValue) break; //No more value
84645eb0 489
490 if (ntotal>=kClusterListSize || ncurrent>=kPadArraySize) {
491 HLTWarning("pad array size exceeded ntotal=%d ncurrent=%d, skip rest of the data", ntotal, ncurrent);
492 break;
493 }
a38a7850 494
495 if(fCurrentRow != newRow){
496 WriteClusters(ntotal,clusterlist);
497
498 lastpad = 123456789;
499
500 currentPt = pad2;
501 previousPt = pad1;
502 nprevious=0;
503 ncurrent=0;
504 ntotal=0;
505
506 fCurrentRow = newRow;
507 }
508
509 pad = newPad;
510 time = newTime;
db16520a 511
a38a7850 512 } // END while(readValue)
513
514 WriteClusters(ntotal,clusterlist);
515
46b33a24 516 HLTInfo("ClusterFinder found %d clusters in slice %d patch %d", fNClusters, fCurrentSlice, fCurrentPatch);
a38a7850 517
518} // ENDEND
519
520void AliHLTTPCClusterFinder::WriteClusters(Int_t nclusters,AliClusterData *list)
521{
522 //write cluster to output pointer
8f8bf0af 523 Int_t thisrow=-1,thissector=-1;
a38a7850 524 UInt_t counter = fNClusters;
525
526 for(int j=0; j<nclusters; j++)
527 {
d8b2f74a 528
529
530
a38a7850 531 if(!list[j].fFlags) continue; //discard single pad clusters
532 if(list[j].fTotalCharge < fThreshold) continue; //noise cluster
533
534 Float_t xyz[3];
535 Float_t fpad =(Float_t)list[j].fPad / list[j].fTotalCharge;
536 Float_t fpad2=fXYErr*fXYErr; //fixed given error
537 Float_t ftime =(Float_t)list[j].fTime / list[j].fTotalCharge;
538 Float_t ftime2=fZErr*fZErr; //fixed given error
539
738c049f 540
aff6e981 541
542 if(fUnsorted){
543 fCurrentRow=list[j].fRow;
544 }
545
738c049f 546
a38a7850 547 if(fCalcerr) { //calc the errors, otherwice take the fixed error
548 Int_t patch = AliHLTTPCTransform::GetPatch(fCurrentRow);
549 UInt_t q2=list[j].fTotalCharge*list[j].fTotalCharge;
550 Float_t sy2=list[j].fPad2 * list[j].fTotalCharge - list[j].fPad * list[j].fPad;
551 sy2/=q2;
552 if(sy2 < 0) {
553 LOG(AliHLTTPCLog::kError,"AliHLTTPCClusterFinder::WriteClusters","Cluster width")
554 <<"SigmaY2 negative "<<sy2<<" on row "<<fCurrentRow<<" "<<fpad<<" "<<ftime<<ENDLOG;
555 continue;
556 } else {
557 if(!fRawSP){
558 fpad2 = (sy2 + 1./12)*AliHLTTPCTransform::GetPadPitchWidth(patch)*AliHLTTPCTransform::GetPadPitchWidth(patch);
559 if(sy2 != 0){
560 fpad2*=0.108; //constants are from offline studies
561 if(patch<2)
562 fpad2*=2.07;
563 }
564 } else fpad2=sy2; //take the width not the error
565 }
566 Float_t sz2=list[j].fTime2*list[j].fTotalCharge - list[j].fTime*list[j].fTime;
567 sz2/=q2;
568 if(sz2 < 0){
569 LOG(AliHLTTPCLog::kError,"AliHLTTPCClusterFinder::WriteClusters","Cluster width")
570 <<"SigmaZ2 negative "<<sz2<<" on row "<<fCurrentRow<<" "<<fpad<<" "<<ftime<<ENDLOG;
571 continue;
572 } else {
573 if(!fRawSP){
574 ftime2 = (sz2 + 1./12)*AliHLTTPCTransform::GetZWidth()*AliHLTTPCTransform::GetZWidth();
575 if(sz2 != 0) {
576 ftime2 *= 0.169; //constants are from offline studies
577 if(patch<2)
578 ftime2 *= 1.77;
579 }
580 } else ftime2=sz2; //take the width, not the error
581 }
582 }
583 if(fStdout==kTRUE)
8252a538 584 HLTInfo("WriteCluster: padrow %d pad %d +- %d time +- %d charge %d",fCurrentRow, fpad, fpad2, ftime, ftime2, list[j].fTotalCharge);
a38a7850 585
586 if(!fRawSP){
587 AliHLTTPCTransform::Slice2Sector(fCurrentSlice,fCurrentRow,thissector,thisrow);
588 AliHLTTPCTransform::Raw2Local(xyz,thissector,thisrow,fpad,ftime);
589
590 if(xyz[0]==0) LOG(AliHLTTPCLog::kError,"AliHLTTPCClustFinder","Cluster Finder")
591 <<AliHLTTPCLog::kDec<<"Zero cluster"<<ENDLOG;
592 if(fNClusters >= fMaxNClusters)
593 {
594 LOG(AliHLTTPCLog::kError,"AliHLTTPCClustFinder::WriteClusters","Cluster Finder")
595 <<AliHLTTPCLog::kDec<<"Too many clusters "<<fNClusters<<ENDLOG;
596 return;
597 }
598
599 fSpacePointData[counter].fX = xyz[0];
600 fSpacePointData[counter].fY = xyz[1];
601 fSpacePointData[counter].fZ = xyz[2];
602
603 } else {
604 fSpacePointData[counter].fX = fCurrentRow;
605 fSpacePointData[counter].fY = fpad;
606 fSpacePointData[counter].fZ = ftime;
607 }
608
609 fSpacePointData[counter].fCharge = list[j].fTotalCharge;
610 fSpacePointData[counter].fPadRow = fCurrentRow;
611 fSpacePointData[counter].fSigmaY2 = fpad2;
612 fSpacePointData[counter].fSigmaZ2 = ftime2;
613
44be0fde 614 fSpacePointData[counter].fUsed = kFALSE; // only used / set in AliHLTTPCDisplay
738c049f 615 fSpacePointData[counter].fTrackN = -1; // only used / set in AliHLTTPCDisplay
44be0fde 616
a38a7850 617 Int_t patch=fCurrentPatch;
618 if(patch==-1) patch=0; //never store negative patch number
619 fSpacePointData[counter].fID = counter
620 +((fCurrentSlice&0x7f)<<25)+((patch&0x7)<<22);//Uli
621
622#ifdef do_mc
623 Int_t trackID[3];
624 GetTrackID((Int_t)rint(fpad),(Int_t)rint(ftime),trackID);
625
626 fSpacePointData[counter].fTrackID[0] = trackID[0];
627 fSpacePointData[counter].fTrackID[1] = trackID[1];
628 fSpacePointData[counter].fTrackID[2] = trackID[2];
629
a38a7850 630#endif
631
632 fNClusters++;
633 counter++;
634 }
635}
636
637// STILL TO FIX ----------------------------------------------------------------------------
638
639#ifdef do_mc
640void AliHLTTPCClusterFinder::GetTrackID(Int_t pad,Int_t time,Int_t *trackID)
641{
642 //get mc id
643 AliHLTTPCDigitRowData *rowPt = (AliHLTTPCDigitRowData*)fDigitRowData;
644
645 trackID[0]=trackID[1]=trackID[2]=-2;
a38a7850 646 for(Int_t i=fFirstRow; i<=fLastRow; i++){
647 if(rowPt->fRow < (UInt_t)fCurrentRow){
648 AliHLTTPCMemHandler::UpdateRowPointer(rowPt);
649 continue;
650 }
651 AliHLTTPCDigitData *digPt = (AliHLTTPCDigitData*)rowPt->fDigitData;
652 for(UInt_t j=0; j<rowPt->fNDigit; j++){
653 Int_t cpad = digPt[j].fPad;
654 Int_t ctime = digPt[j].fTime;
655 if(cpad != pad) continue;
656 if(ctime != time) continue;
657
658 trackID[0] = digPt[j].fTrackID[0];
659 trackID[1] = digPt[j].fTrackID[1];
660 trackID[2] = digPt[j].fTrackID[2];
661
a38a7850 662 break;
663 }
664 break;
665 }
666}
667#endif
01f43166 668
669//----------------------------------Methods for the new unsorted way of reading the data --------------------------------
670
a74855c2 671void AliHLTTPCClusterFinder::ReadDataUnsorted(void* ptr,unsigned long size)
64defa03 672{
01f43166 673 //set input pointer
674 fPtr = (UChar_t*)ptr;
675 fSize = size;
676
8252a538 677 if(!fVectorInitialized){
678 InitializePadArray();
679 }
b1c46961 680
8252a538 681 fDigitReader->InitBlock(fPtr,fSize,fFirstRow,fLastRow,fCurrentPatch,fCurrentSlice);
f5b70376 682
8252a538 683 while(fDigitReader->NextChannel()){
684 UInt_t row=fDigitReader->GetRow();
685 UInt_t pad=fDigitReader->GetPad();
70a4e20c 686
8252a538 687 fRowPadVector[row][pad]->ClearCandidates();
688 while(fDigitReader->NextBunch()){
689 if(fDigitReader->GetBunchSize()>1){//to remove single timebin values, this will have to change at some point
690 const UInt_t *bunchData= fDigitReader->GetSignals();
691 UInt_t time = fDigitReader->GetTime();
692 AliHLTTPCClusters candidate;
693 for(Int_t i=0;i<fDigitReader->GetBunchSize();i++){
694 candidate.fTotalCharge+=bunchData[i];
695 candidate.fTime += time*bunchData[i];
696 candidate.fTime2 += time*time*bunchData[i];
697 time++;
698 }
699 if(candidate.fTotalCharge>0){
700 candidate.fMean=candidate.fTime/candidate.fTotalCharge;
701 candidate.fPad=candidate.fTotalCharge*pad;
702 candidate.fPad2=candidate.fPad*pad;
703 candidate.fLastMergedPad=pad;
d2f725e4 704 candidate.fRowNumber=row+fDigitReader->GetRowOffset();
8252a538 705 }
706 fRowPadVector[row][pad]->AddClusterCandidate(candidate);
707 }
708 }
b1c46961 709 }
8252a538 710}
711
712Bool_t AliHLTTPCClusterFinder::ComparePads(AliHLTTPCPad *nextPad,AliHLTTPCClusters* cluster,Int_t nextPadToRead){
713 //Checking if we have a match on the next pad
a74855c2 714 for(UInt_t candidateNumber=0;candidateNumber<nextPad->fClusterCandidates.size();candidateNumber++){
8252a538 715 AliHLTTPCClusters *candidate =&nextPad->fClusterCandidates[candidateNumber];
716 if(cluster->fMean-candidate->fMean==1 || candidate->fMean-cluster->fMean==1 || cluster->fMean-candidate->fMean==0){
717 cluster->fMean=candidate->fMean;
718 cluster->fTotalCharge+=candidate->fTotalCharge;
719 cluster->fTime += candidate->fTime;
720 cluster->fTime2 += candidate->fTime2;
721 cluster->fPad+=candidate->fPad;
722 cluster->fPad2=candidate->fPad2;
723 cluster->fLastMergedPad=candidate->fPad;
724
725 //setting the matched pad to used
726 nextPad->fUsedClusterCandidates[candidateNumber]=1;
727 nextPadToRead++;
a74855c2 728 if(nextPadToRead<(Int_t)fNumberOfPadsInRow[fRowOfFirstCandidate]){
8252a538 729 nextPad=fRowPadVector[fRowOfFirstCandidate][nextPadToRead];
730 ComparePads(nextPad,cluster,nextPadToRead);
731 }
732 else{
733 return kFALSE;
734 }
735 }
736 else{
737 return kFALSE;
738 }
b1c46961 739 }
8252a538 740 return kFALSE;
01f43166 741}
64defa03 742
743void AliHLTTPCClusterFinder::FindClusters()
744{
b1c46961 745 // see header file for function documentation
8252a538 746
747 AliHLTTPCClusters* tmpCandidate=NULL;
a74855c2 748 for(UInt_t row=0;row<fNumberOfRows;row++){
8252a538 749 fRowOfFirstCandidate=row;
a74855c2 750 for(UInt_t pad=0;pad<fNumberOfPadsInRow[row]-1;pad++){
8252a538 751 AliHLTTPCPad *tmpPad=fRowPadVector[row][pad];
752 for(size_t candidate=0;candidate<tmpPad->fClusterCandidates.size();candidate++){
753 if(tmpPad->fUsedClusterCandidates[candidate]){
754 continue;
755 }
756 tmpCandidate=&tmpPad->fClusterCandidates[candidate];
757 UInt_t tmpTotalCharge=tmpCandidate->fTotalCharge;
758 ComparePads(fRowPadVector[row][pad+1],tmpCandidate,pad+1);
759 if(tmpCandidate->fTotalCharge>tmpTotalCharge){
760 //we have a cluster
761 fClusters.push_back(*tmpCandidate);
762 }
763 }
764 }
01f43166 765 }
8252a538 766
767 HLTInfo("Found %d clusters.",fClusters.size());
768
769 //TODO: Change so it stores AliHLTTPCSpacePointData directly, instead of this copying
770
771 AliClusterData * clusterlist = new AliClusterData[fClusters.size()]; //Clusterlist
772 for(unsigned int i=0;i<fClusters.size();i++){
773 clusterlist[i].fTotalCharge = fClusters[i].fTotalCharge;
774 clusterlist[i].fPad = fClusters[i].fPad;
775 clusterlist[i].fPad2 = fClusters[i].fPad2;
776 clusterlist[i].fTime = fClusters[i].fTime;
777 clusterlist[i].fTime2 = fClusters[i].fTime2;
778 clusterlist[i].fMean = fClusters[i].fMean;
779 clusterlist[i].fFlags = fClusters[i].fFlags;
780 clusterlist[i].fChargeFalling = fClusters[i].fChargeFalling;
781 clusterlist[i].fLastCharge = fClusters[i].fLastCharge;
782 clusterlist[i].fLastMergedPad = fClusters[i].fLastMergedPad;
783 clusterlist[i].fRow = fClusters[i].fRowNumber;
784 }
785 // PrintClusters();
786 WriteClusters(fClusters.size(),clusterlist);
e83e889b 787 delete [] clusterlist;
8252a538 788 fClusters.clear();
01f43166 789}
64defa03 790
8252a538 791void AliHLTTPCClusterFinder::PrintClusters()
792{
793 // see header file for class documentation
794 for(size_t i=0;i<fClusters.size();i++){
795 HLTInfo("Cluster number: %d",i);
796 HLTInfo("Row: %d \t Pad: %d",fClusters[i].fRowNumber,fClusters[i].fFirstPad);
797 HLTInfo("Total Charge: %d",fClusters[i].fTotalCharge);
798 HLTInfo("fPad: %d",fClusters[i].fPad);
799 HLTInfo("PadError: %d",fClusters[i].fPad2);
800 HLTInfo("TimeMean: %d",fClusters[i].fTime);
801 HLTInfo("TimeError: %d",fClusters[i].fTime2);
802 HLTInfo("EndOfCluster:");
803 }
804}
805
01f43166 806void AliHLTTPCClusterFinder::WriteClusters(Int_t nclusters,AliHLTTPCClusters *list)//This is used when using the AliHLTTPCClusters class for cluster data
807{
808 //write cluster to output pointer
809 Int_t thisrow,thissector;
810 UInt_t counter = fNClusters;
811
812 for(int j=0; j<nclusters; j++)
813 {
814 if(!list[j].fFlags) continue; //discard single pad clusters
815 if(list[j].fTotalCharge < fThreshold) continue; //noise cluster
816
817 Float_t xyz[3];
818 Float_t fpad =(Float_t)list[j].fPad / list[j].fTotalCharge;
819 Float_t fpad2=fXYErr*fXYErr; //fixed given error
820 Float_t ftime =(Float_t)list[j].fTime / list[j].fTotalCharge;
821 Float_t ftime2=fZErr*fZErr; //fixed given error
822
d8b2f74a 823
01f43166 824 if(fCalcerr) { //calc the errors, otherwice take the fixed error
825 Int_t patch = AliHLTTPCTransform::GetPatch(fCurrentRow);
826 UInt_t q2=list[j].fTotalCharge*list[j].fTotalCharge;
827 Float_t sy2=list[j].fPad2 * list[j].fTotalCharge - list[j].fPad * list[j].fPad;
828 sy2/=q2;
829 if(sy2 < 0) {
830 LOG(AliHLTTPCLog::kError,"AliHLTTPCClusterFinder::WriteClusters","Cluster width")
831 <<"SigmaY2 negative "<<sy2<<" on row "<<fCurrentRow<<" "<<fpad<<" "<<ftime<<ENDLOG;
832 continue;
833 } else {
834 if(!fRawSP){
835 fpad2 = (sy2 + 1./12)*AliHLTTPCTransform::GetPadPitchWidth(patch)*AliHLTTPCTransform::GetPadPitchWidth(patch);
836 if(sy2 != 0){
837 fpad2*=0.108; //constants are from offline studies
838 if(patch<2)
839 fpad2*=2.07;
840 }
841 } else fpad2=sy2; //take the width not the error
842 }
843 Float_t sz2=list[j].fTime2*list[j].fTotalCharge - list[j].fTime*list[j].fTime;
844 sz2/=q2;
845 if(sz2 < 0){
846 LOG(AliHLTTPCLog::kError,"AliHLTTPCClusterFinder::WriteClusters","Cluster width")
847 <<"SigmaZ2 negative "<<sz2<<" on row "<<fCurrentRow<<" "<<fpad<<" "<<ftime<<ENDLOG;
848 continue;
849 } else {
850 if(!fRawSP){
851 ftime2 = (sz2 + 1./12)*AliHLTTPCTransform::GetZWidth()*AliHLTTPCTransform::GetZWidth();
852 if(sz2 != 0) {
853 ftime2 *= 0.169; //constants are from offline studies
854 if(patch<2)
855 ftime2 *= 1.77;
856 }
857 } else ftime2=sz2; //take the width, not the error
858 }
859 }
860 if(fStdout==kTRUE)
8252a538 861 HLTInfo("WriteCluster: padrow %d pad %d +- %d time +- %d charge %d",fCurrentRow, fpad, fpad2, ftime, ftime2, list[j].fTotalCharge);
862
01f43166 863 if(!fRawSP){
864 AliHLTTPCTransform::Slice2Sector(fCurrentSlice,fCurrentRow,thissector,thisrow);
865 AliHLTTPCTransform::Raw2Local(xyz,thissector,thisrow,fpad,ftime);
866
867 if(xyz[0]==0) LOG(AliHLTTPCLog::kError,"AliHLTTPCClustFinder","Cluster Finder")
868 <<AliHLTTPCLog::kDec<<"Zero cluster"<<ENDLOG;
869 if(fNClusters >= fMaxNClusters)
870 {
871 LOG(AliHLTTPCLog::kError,"AliHLTTPCClustFinder::WriteClusters","Cluster Finder")
872 <<AliHLTTPCLog::kDec<<"Too many clusters "<<fNClusters<<ENDLOG;
873 return;
874 }
875
876 fSpacePointData[counter].fX = xyz[0];
877 fSpacePointData[counter].fY = xyz[1];
878 fSpacePointData[counter].fZ = xyz[2];
879
880 } else {
881 fSpacePointData[counter].fX = fCurrentRow;
882 fSpacePointData[counter].fY = fpad;
883 fSpacePointData[counter].fZ = ftime;
884 }
885
886 fSpacePointData[counter].fCharge = list[j].fTotalCharge;
887 fSpacePointData[counter].fPadRow = fCurrentRow;
888 fSpacePointData[counter].fSigmaY2 = fpad2;
889 fSpacePointData[counter].fSigmaZ2 = ftime2;
890
891 fSpacePointData[counter].fUsed = kFALSE; // only used / set in AliHLTTPCDisplay
892 fSpacePointData[counter].fTrackN = -1; // only used / set in AliHLTTPCDisplay
893
894 Int_t patch=fCurrentPatch;
895 if(patch==-1) patch=0; //never store negative patch number
896 fSpacePointData[counter].fID = counter
897 +((fCurrentSlice&0x7f)<<25)+((patch&0x7)<<22);//Uli
898
899#ifdef do_mc
900 Int_t trackID[3];
901 GetTrackID((Int_t)rint(fpad),(Int_t)rint(ftime),trackID);
902
903 fSpacePointData[counter].fTrackID[0] = trackID[0];
904 fSpacePointData[counter].fTrackID[1] = trackID[1];
905 fSpacePointData[counter].fTrackID[2] = trackID[2];
906
01f43166 907#endif
908
909 fNClusters++;
910 counter++;
911 }
912}