]> git.uio.no Git - u/mrichter/AliRoot.git/blame - HLT/TPCLib/AliHLTTPCClusterFinder.cxx
added cutoff parameter in z direction to ignore clusters of large z (Gaute)
[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"
a38a7850 33#include "AliHLTTPCSpacePointData.h"
34#include "AliHLTTPCMemHandler.h"
46b33a24 35#include "AliHLTTPCPad.h"
8252a538 36#include <sys/time.h>
a38a7850 37
38#if __GNUC__ >= 3
39using namespace std;
40#endif
41
a38a7850 42ClassImp(AliHLTTPCClusterFinder)
43
44AliHLTTPCClusterFinder::AliHLTTPCClusterFinder()
46b33a24 45 :
2fdb1ae7 46 fClustersHWAddressVector(),
47 fRowPadVector(),
2a083ac4 48 fSpacePointData(NULL),
49 fDigitReader(NULL),
50 fPtr(NULL),
51 fSize(0),
6b15c309 52 fDeconvTime(kFALSE),
53 fDeconvPad(kFALSE),
46b33a24 54 fStdout(kFALSE),
55 fCalcerr(kTRUE),
56 fRawSP(kFALSE),
57 fFirstRow(0),
58 fLastRow(0),
2a083ac4 59 fCurrentRow(0),
60 fCurrentSlice(0),
61 fCurrentPatch(0),
62 fMatch(1),
63 fThreshold(10),
2a083ac4 64 fNClusters(0),
65 fMaxNClusters(0),
66 fXYErr(0.2),
67 fZErr(0.3),
01f43166 68 fOccupancyLimit(1.0),
64defa03 69 fUnsorted(0),
a74855c2 70 fVectorInitialized(kFALSE),
8252a538 71 fClusters(),
a74855c2 72 fNumberOfPadsInRow(NULL),
73 fNumberOfRows(0),
2fdb1ae7 74 fRowOfFirstCandidate(0),
6b15c309 75 fDoPadSelection(kFALSE),
76 fFirstTimeBin(0),
77 fLastTimeBin(AliHLTTPCTransform::GetNTimeBins()),
78 fTotalChargeOfPreviousClusterCandidate(0),
79 fChargeOfCandidatesFalling(kFALSE)
a38a7850 80{
8252a538 81 //constructor
46b33a24 82}
a38a7850 83
a38a7850 84AliHLTTPCClusterFinder::~AliHLTTPCClusterFinder()
85{
86 //destructor
8252a538 87 if(fVectorInitialized){
88 DeInitializePadArray();
89 }
90 if(fNumberOfPadsInRow){
91 delete [] fNumberOfPadsInRow;
92 fNumberOfPadsInRow=NULL;
93 }
a38a7850 94}
95
96void AliHLTTPCClusterFinder::InitSlice(Int_t slice,Int_t patch,Int_t firstrow, Int_t lastrow,Int_t nmaxpoints)
97{
98 //init slice
99 fNClusters = 0;
100 fMaxNClusters = nmaxpoints;
101 fCurrentSlice = slice;
102 fCurrentPatch = patch;
103 fFirstRow = firstrow;
104 fLastRow = lastrow;
105}
106
8252a538 107void AliHLTTPCClusterFinder::InitializePadArray(){
108 // see header file for class documentation
109
110 if(fCurrentPatch>5||fCurrentPatch<0){
111 HLTFatal("Patch is not set");
112 return;
113 }
114
115 HLTDebug("Patch number=%d",fCurrentPatch);
116
117 fFirstRow = AliHLTTPCTransform::GetFirstRow(fCurrentPatch);
118 fLastRow = AliHLTTPCTransform::GetLastRow(fCurrentPatch);
119
120 fNumberOfRows=fLastRow-fFirstRow+1;
121 fNumberOfPadsInRow= new UInt_t[fNumberOfRows];
122
123 memset( fNumberOfPadsInRow, 0, sizeof(Int_t)*(fNumberOfRows));
124
a74855c2 125 for(UInt_t i=0;i<fNumberOfRows;i++){
8252a538 126 fNumberOfPadsInRow[i]=AliHLTTPCTransform::GetNPads(i+fFirstRow);
127 AliHLTTPCPadVector tmpRow;
a74855c2 128 for(UInt_t j=0;j<fNumberOfPadsInRow[i];j++){
8252a538 129 AliHLTTPCPad *tmpPad = new AliHLTTPCPad(2);
130 tmpPad->SetID(i,j);
131 tmpRow.push_back(tmpPad);
132 }
133 fRowPadVector.push_back(tmpRow);
134 }
135 fVectorInitialized=kTRUE;
136}
137
138Int_t AliHLTTPCClusterFinder::DeInitializePadArray()
139{
140 // see header file for class documentation
a74855c2 141 for(UInt_t i=0;i<fNumberOfRows;i++){
142 for(UInt_t j=0;j<fNumberOfPadsInRow[i];j++){
8252a538 143 delete fRowPadVector[i][j];
144 fRowPadVector[i][j]=NULL;
145 }
146 fRowPadVector[i].clear();
147 }
148 fRowPadVector.clear();
149 return 1;
150}
151
152
a38a7850 153void AliHLTTPCClusterFinder::InitSlice(Int_t slice,Int_t patch,Int_t nmaxpoints)
154{
155 //init slice
156 fNClusters = 0;
157 fMaxNClusters = nmaxpoints;
158 fCurrentSlice = slice;
159 fCurrentPatch = patch;
160 fFirstRow=AliHLTTPCTransform::GetFirstRow(patch);
161 fLastRow=AliHLTTPCTransform::GetLastRow(patch);
162}
163
164void AliHLTTPCClusterFinder::SetOutputArray(AliHLTTPCSpacePointData *pt)
165{
166 //set pointer to output
167 fSpacePointData = pt;
168}
169
170void AliHLTTPCClusterFinder::Read(void* ptr,unsigned long size){
171 //set input pointer
172 fPtr = (UChar_t*)ptr;
173 fSize = size;
174}
175
176void AliHLTTPCClusterFinder::ProcessDigits()
177{
6b0fdc0e 178 int iResult=0;
a38a7850 179 bool readValue = true;
180 Int_t newRow = 0;
181 Int_t rowOffset = 0;
46b33a24 182 UShort_t time=0,newTime=0;
183 UInt_t pad=0,newPad=0;
184 AliHLTTPCSignal_t charge=0;
a38a7850 185
186 fNClusters = 0;
187
188 // initialize block for reading packed data
67fada6b 189 iResult=fDigitReader->InitBlock(fPtr,fSize,fFirstRow,fLastRow,fCurrentPatch,fCurrentSlice);
190 if (iResult<0) return;
191
a38a7850 192 readValue = fDigitReader->Next();
193
5235c3e9 194 // Matthias 08.11.2006 the following return would cause termination without writing the
6c1a9d9e 195 // ClusterData and thus would block the component. I just want to have the commented line
5235c3e9 196 // here for information
197 //if (!readValue)return;
db16520a 198
a38a7850 199 pad = fDigitReader->GetPad();
200 time = fDigitReader->GetTime();
201 fCurrentRow = fDigitReader->GetRow();
202
203 if ( fCurrentPatch >= 2 ) // Outer sector, patches 2, 3, 4, 5
204 rowOffset = AliHLTTPCTransform::GetFirstRow( 2 );
205
206 fCurrentRow += rowOffset;
207
208 UInt_t lastpad = 123456789;
2a083ac4 209 const UInt_t kPadArraySize=5000;
210 const UInt_t kClusterListSize=10000;
84645eb0 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
a38a7850 214
215 AliClusterData **currentPt; //List of pointers to the current pad
216 AliClusterData **previousPt; //List of pointers to the previous pad
217 currentPt = pad2;
218 previousPt = pad1;
219 UInt_t nprevious=0,ncurrent=0,ntotal=0;
220
46b33a24 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
226 bins.
227 */
228 Int_t gatingGridOffset=50;
6b15c309 229 if(fFirstTimeBin>0){
230 gatingGridOffset=fFirstTimeBin;
231 }
46b33a24 232 AliHLTTPCPad baseline(gatingGridOffset, AliHLTTPCTransform::GetNTimeBins());
233 // just to make later conversion to a list of objects easier
84645eb0 234 AliHLTTPCPad* pCurrentPad=NULL;
6b15c309 235 /*
236 if (fSignalThreshold>=0) {
84645eb0 237 pCurrentPad=&baseline;
238 baseline.SetThreshold(fSignalThreshold);
239 }
6b15c309 240 */
6b0fdc0e 241 while ( readValue!=0 && iResult>=0){ // Reads through all digits in block
242 iResult=0;
a38a7850 243
244 if(pad != lastpad){
245 //This is a new pad
246
247 //Switch the lists:
248 if(currentPt == pad2){
249 currentPt = pad1;
250 previousPt = pad2;
251 }
252 else {
253 currentPt = pad2;
254 previousPt = pad1;
255 }
256 nprevious = ncurrent;
257 ncurrent = 0;
258 if(pad != lastpad+1){
259 //this happens if there is a pad with no signal.
260 nprevious = ncurrent = 0;
261 }
262 lastpad = pad;
263 }
264
265 Bool_t newcluster = kTRUE;
266 UInt_t seqcharge=0,seqaverage=0,seqerror=0;
2a083ac4 267 AliHLTTPCSignal_t lastcharge=0;
268 UInt_t bLastWasFalling=0;
a38a7850 269 Int_t newbin=-1;
270
271
272 if(fDeconvTime){
273 redo: //This is a goto.
274
275 if(newbin > -1){
276 //bin = newbin;
277 newbin = -1;
278 }
279
280 lastcharge=0;
2a083ac4 281 bLastWasFalling = 0;
a38a7850 282 }
283
6b0fdc0e 284 while(iResult>=0){ //Loop over time bins of current pad
46b33a24 285 // read all the values for one pad at once to calculate the base line
286 if (pCurrentPad) {
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) {
291 do {
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);
297 }
298 pCurrentPad->CalculateBaseLine(AliHLTTPCTransform::GetNTimeBins()/2);
299 if (pCurrentPad->Next(kTRUE/*do zero suppression*/)==0) {
84645eb0 300 //HLTDebug("no data available after zero suppression");
46b33a24 301 pCurrentPad->StopEvent();
302 pCurrentPad->ResetHistory();
303 break;
304 }
305 time=pCurrentPad->GetCurrentPosition();
306 if (time>pCurrentPad->GetSize()) {
307 HLTError("invalid time bin for pad");
308 break;
309 }
310 }
311 }
46b33a24 312 if (pCurrentPad) {
5235c3e9 313 Float_t occupancy=pCurrentPad->GetOccupancy();
314 //HLTDebug("pad %d occupancy level: %f", pCurrentPad->GetPadNumber(), occupancy);
315 if ( occupancy < fOccupancyLimit ) {
316 charge = pCurrentPad->GetCorrectedData();
317 } else {
318 charge = 0;
319 //HLTDebug("ignoring pad %d with occupancy level %f", pCurrentPad->GetPadNumber(), occupancy);
320 }
46b33a24 321 } else {
5235c3e9 322 charge = fDigitReader->GetSignal();
46b33a24 323 }
324 //HLTDebug("get next charge value: position %d charge %d", time, charge);
a38a7850 325
738c049f 326
327 // CHARGE DEBUG
328 if (fDigitReader->GetRow() == 90){
329///// LOG(AliHLTTPCLog::kFatal,"AliHLTTPCClusterFinder::Row","row90") << "PAD=" << fDigitReader->GetPad() << " TIME=" << fDigitReader->GetTime()
330 // << " SIGNAL=" << fDigitReader->GetSignal() << ENDLOG;
331
332 }
333
a38a7850 334 if(time >= AliHLTTPCTransform::GetNTimeBins()){
6b0fdc0e 335 HLTWarning("Pad %d: Timebin (%d) out of range (%d)", pad, time, AliHLTTPCTransform::GetNTimeBins());
336 iResult=-ERANGE;
a38a7850 337 }
46b33a24 338
339
a38a7850 340 //Get the current ADC-value
341 if(fDeconvTime){
342
343 //Check if the last pixel in the sequence is smaller than this
344 if(charge > lastcharge){
2a083ac4 345 if(bLastWasFalling){
a38a7850 346 newbin = 1;
347 break;
348 }
349 }
2a083ac4 350 else bLastWasFalling = 1; //last pixel was larger than this
a38a7850 351 lastcharge = charge;
352 }
353
354 //Sum the total charge of this sequence
355 seqcharge += charge;
356 seqaverage += time*charge;
357 seqerror += time*time*charge;
358
46b33a24 359 if (pCurrentPad) {
360
361 if((pCurrentPad->Next(kTRUE/*do zero suppression*/))==0) {
362 pCurrentPad->StopEvent();
363 pCurrentPad->ResetHistory();
364 if(readValue) {
365 newPad = fDigitReader->GetPad();
366 newTime = fDigitReader->GetTime();
367 newRow = fDigitReader->GetRow() + rowOffset;
368 }
369 break;
370 }
371
372 newPad=pCurrentPad->GetPadNumber();
373 newTime=pCurrentPad->GetCurrentPosition();
374 newRow=pCurrentPad->GetRowNumber();
375 } else {
a38a7850 376 readValue = fDigitReader->Next();
a38a7850 377 //Check where to stop:
378 if(!readValue) break; //No more value
379
380 newPad = fDigitReader->GetPad();
381 newTime = fDigitReader->GetTime();
382 newRow = fDigitReader->GetRow() + rowOffset;
46b33a24 383 }
a38a7850 384
385 if(newPad != pad)break; //new pad
386 if(newTime != time+1) break; //end of sequence
6b0fdc0e 387 if(iResult<0) break;
a38a7850 388
389 // pad = newpad; is equal
390 time = newTime;
391
392 }//end loop over sequence
393
46b33a24 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);
396 if (seqcharge<=0) {
397 // with active zero suppression zero values are possible
398 continue;
399 }
a38a7850 400
401 //Calculate mean of sequence:
402 Int_t seqmean=0;
403 if(seqcharge)
404 seqmean = seqaverage/seqcharge;
405 else{
406 LOG(AliHLTTPCLog::kFatal,"AliHLTTPCClusterFinder::ProcessRow","Data")
407 <<"Error in data given to the cluster finder"<<ENDLOG;
408 seqmean = 1;
409 seqcharge = 1;
410 }
411
412 //Calculate mean in pad direction:
413 Int_t padmean = seqcharge*pad;
414 Int_t paderror = pad*padmean;
415
a38a7850 416 //Compare with results on previous pad:
84645eb0 417 for(UInt_t p=0; p<nprevious && p<kPadArraySize && ncurrent<kPadArraySize; p++){
a38a7850 418
419 //dont merge sequences on the same pad twice
420 if(previousPt[p]->fLastMergedPad==pad) continue;
421
422 Int_t difference = seqmean - previousPt[p]->fMean;
423 if(difference < -fMatch) break;
424
425 if(difference <= fMatch){ //There is a match here!!
426 AliClusterData *local = previousPt[p];
427
428 if(fDeconvPad){
429 if(seqcharge > local->fLastCharge){
430 if(local->fChargeFalling){ //The previous pad was falling
431 break; //create a new cluster
432 }
433 }
434 else local->fChargeFalling = 1;
435 local->fLastCharge = seqcharge;
436 }
437
438 //Don't create a new cluster, because we found a match
439 newcluster = kFALSE;
440
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;
450
451 currentPt[ncurrent] = local;
452 ncurrent++;
453
454 break;
455 } //Checking for match at previous pad
456 } //Loop over results on previous pad.
457
84645eb0 458 if(newcluster && ncurrent<kPadArraySize){
a38a7850 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.
462
463 //Add to the clusterlist:
464 AliClusterData *tmp = &clusterlist[ntotal];
465 tmp->fTotalCharge = seqcharge;
466 tmp->fPad = padmean;
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;
473
474 if(fDeconvPad){
475 tmp->fChargeFalling = 0;
476 tmp->fLastCharge = seqcharge;
477 }
478
479 //Update list of pointers to previous pad:
480 currentPt[ncurrent] = &clusterlist[ntotal];
481 ntotal++;
482 ncurrent++;
483 }
484
485 if(fDeconvTime)
486 if(newbin >= 0) goto redo;
487
488 // to prevent endless loop
489 if(time >= AliHLTTPCTransform::GetNTimeBins()){
46b33a24 490 HLTWarning("Timebin (%d) out of range (%d)", time, AliHLTTPCTransform::GetNTimeBins());
a38a7850 491 break;
492 }
493
494
495 if(!readValue) break; //No more value
84645eb0 496
497 if (ntotal>=kClusterListSize || ncurrent>=kPadArraySize) {
498 HLTWarning("pad array size exceeded ntotal=%d ncurrent=%d, skip rest of the data", ntotal, ncurrent);
499 break;
500 }
a38a7850 501
502 if(fCurrentRow != newRow){
503 WriteClusters(ntotal,clusterlist);
504
505 lastpad = 123456789;
506
507 currentPt = pad2;
508 previousPt = pad1;
509 nprevious=0;
510 ncurrent=0;
511 ntotal=0;
512
513 fCurrentRow = newRow;
514 }
515
516 pad = newPad;
517 time = newTime;
db16520a 518
a38a7850 519 } // END while(readValue)
520
521 WriteClusters(ntotal,clusterlist);
522
46b33a24 523 HLTInfo("ClusterFinder found %d clusters in slice %d patch %d", fNClusters, fCurrentSlice, fCurrentPatch);
a38a7850 524
525} // ENDEND
526
527void AliHLTTPCClusterFinder::WriteClusters(Int_t nclusters,AliClusterData *list)
528{
529 //write cluster to output pointer
8f8bf0af 530 Int_t thisrow=-1,thissector=-1;
a38a7850 531 UInt_t counter = fNClusters;
532
533 for(int j=0; j<nclusters; j++)
534 {
d8b2f74a 535
536
537
a38a7850 538 if(!list[j].fFlags) continue; //discard single pad clusters
539 if(list[j].fTotalCharge < fThreshold) continue; //noise cluster
540
541 Float_t xyz[3];
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
546
738c049f 547
aff6e981 548
549 if(fUnsorted){
550 fCurrentRow=list[j].fRow;
551 }
552
738c049f 553
a38a7850 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;
558 sy2/=q2;
559 if(sy2 < 0) {
560 LOG(AliHLTTPCLog::kError,"AliHLTTPCClusterFinder::WriteClusters","Cluster width")
561 <<"SigmaY2 negative "<<sy2<<" on row "<<fCurrentRow<<" "<<fpad<<" "<<ftime<<ENDLOG;
562 continue;
563 } else {
564 if(!fRawSP){
565 fpad2 = (sy2 + 1./12)*AliHLTTPCTransform::GetPadPitchWidth(patch)*AliHLTTPCTransform::GetPadPitchWidth(patch);
566 if(sy2 != 0){
567 fpad2*=0.108; //constants are from offline studies
568 if(patch<2)
569 fpad2*=2.07;
570 }
571 } else fpad2=sy2; //take the width not the error
572 }
573 Float_t sz2=list[j].fTime2*list[j].fTotalCharge - list[j].fTime*list[j].fTime;
574 sz2/=q2;
575 if(sz2 < 0){
576 LOG(AliHLTTPCLog::kError,"AliHLTTPCClusterFinder::WriteClusters","Cluster width")
577 <<"SigmaZ2 negative "<<sz2<<" on row "<<fCurrentRow<<" "<<fpad<<" "<<ftime<<ENDLOG;
578 continue;
579 } else {
580 if(!fRawSP){
581 ftime2 = (sz2 + 1./12)*AliHLTTPCTransform::GetZWidth()*AliHLTTPCTransform::GetZWidth();
582 if(sz2 != 0) {
583 ftime2 *= 0.169; //constants are from offline studies
584 if(patch<2)
585 ftime2 *= 1.77;
586 }
587 } else ftime2=sz2; //take the width, not the error
588 }
589 }
590 if(fStdout==kTRUE)
8252a538 591 HLTInfo("WriteCluster: padrow %d pad %d +- %d time +- %d charge %d",fCurrentRow, fpad, fpad2, ftime, ftime2, list[j].fTotalCharge);
a38a7850 592
593 if(!fRawSP){
594 AliHLTTPCTransform::Slice2Sector(fCurrentSlice,fCurrentRow,thissector,thisrow);
595 AliHLTTPCTransform::Raw2Local(xyz,thissector,thisrow,fpad,ftime);
596
597 if(xyz[0]==0) LOG(AliHLTTPCLog::kError,"AliHLTTPCClustFinder","Cluster Finder")
598 <<AliHLTTPCLog::kDec<<"Zero cluster"<<ENDLOG;
599 if(fNClusters >= fMaxNClusters)
600 {
601 LOG(AliHLTTPCLog::kError,"AliHLTTPCClustFinder::WriteClusters","Cluster Finder")
602 <<AliHLTTPCLog::kDec<<"Too many clusters "<<fNClusters<<ENDLOG;
603 return;
604 }
605
606 fSpacePointData[counter].fX = xyz[0];
6b15c309 607 // fSpacePointData[counter].fY = xyz[1];
608 if(fCurrentSlice<18){
609 fSpacePointData[counter].fY = xyz[1];
610 }
611 else{
612 fSpacePointData[counter].fY = -1*xyz[1];
613 }
a38a7850 614 fSpacePointData[counter].fZ = xyz[2];
6b15c309 615
a38a7850 616 } else {
617 fSpacePointData[counter].fX = fCurrentRow;
618 fSpacePointData[counter].fY = fpad;
619 fSpacePointData[counter].fZ = ftime;
620 }
621
622 fSpacePointData[counter].fCharge = list[j].fTotalCharge;
623 fSpacePointData[counter].fPadRow = fCurrentRow;
624 fSpacePointData[counter].fSigmaY2 = fpad2;
625 fSpacePointData[counter].fSigmaZ2 = ftime2;
626
6b15c309 627 fSpacePointData[counter].fMaxQ = list[j].fQMax;
628
44be0fde 629 fSpacePointData[counter].fUsed = kFALSE; // only used / set in AliHLTTPCDisplay
738c049f 630 fSpacePointData[counter].fTrackN = -1; // only used / set in AliHLTTPCDisplay
44be0fde 631
a38a7850 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
636
637#ifdef do_mc
638 Int_t trackID[3];
639 GetTrackID((Int_t)rint(fpad),(Int_t)rint(ftime),trackID);
640
641 fSpacePointData[counter].fTrackID[0] = trackID[0];
642 fSpacePointData[counter].fTrackID[1] = trackID[1];
643 fSpacePointData[counter].fTrackID[2] = trackID[2];
644
a38a7850 645#endif
646
647 fNClusters++;
648 counter++;
649 }
650}
651
652// STILL TO FIX ----------------------------------------------------------------------------
653
654#ifdef do_mc
655void AliHLTTPCClusterFinder::GetTrackID(Int_t pad,Int_t time,Int_t *trackID)
656{
657 //get mc id
658 AliHLTTPCDigitRowData *rowPt = (AliHLTTPCDigitRowData*)fDigitRowData;
659
660 trackID[0]=trackID[1]=trackID[2]=-2;
a38a7850 661 for(Int_t i=fFirstRow; i<=fLastRow; i++){
662 if(rowPt->fRow < (UInt_t)fCurrentRow){
663 AliHLTTPCMemHandler::UpdateRowPointer(rowPt);
664 continue;
665 }
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;
672
673 trackID[0] = digPt[j].fTrackID[0];
674 trackID[1] = digPt[j].fTrackID[1];
675 trackID[2] = digPt[j].fTrackID[2];
676
a38a7850 677 break;
678 }
679 break;
680 }
681}
682#endif
01f43166 683
684//----------------------------------Methods for the new unsorted way of reading the data --------------------------------
685
a74855c2 686void AliHLTTPCClusterFinder::ReadDataUnsorted(void* ptr,unsigned long size)
64defa03 687{
01f43166 688 //set input pointer
689 fPtr = (UChar_t*)ptr;
690 fSize = size;
691
8252a538 692 if(!fVectorInitialized){
693 InitializePadArray();
694 }
b1c46961 695
8252a538 696 fDigitReader->InitBlock(fPtr,fSize,fFirstRow,fLastRow,fCurrentPatch,fCurrentSlice);
f5b70376 697
8252a538 698 while(fDigitReader->NextChannel()){
699 UInt_t row=fDigitReader->GetRow();
700 UInt_t pad=fDigitReader->GetPad();
70a4e20c 701
8252a538 702 while(fDigitReader->NextBunch()){
703 if(fDigitReader->GetBunchSize()>1){//to remove single timebin values, this will have to change at some point
8252a538 704 UInt_t time = fDigitReader->GetTime();
6b15c309 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];
714 }
715 time++;
716 }
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();
723 }
724 fRowPadVector[row][pad]->AddClusterCandidate(candidate);
8252a538 725 }
6b15c309 726 }
727 }
728 }
729}
730
731void AliHLTTPCClusterFinder::ReadDataUnsortedDeconvoluteTime(void* ptr,unsigned long size)
732{
733 //set input pointer
734 fPtr = (UChar_t*)ptr;
735 fSize = size;
736
737 if(!fVectorInitialized){
738 InitializePadArray();
739 }
740
741 fDigitReader->InitBlock(fPtr,fSize,fFirstRow,fLastRow,fCurrentPatch,fCurrentSlice);
742
743 while(fDigitReader->NextChannel()){
744 UInt_t row=fDigitReader->GetRow();
745 UInt_t pad=fDigitReader->GetPad();
746
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;
753 UInt_t prevSignal=0;
754 Bool_t signalFalling=kFALSE;
755 const UInt_t *bunchData= fDigitReader->GetSignals();
756 do{
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;
763 prevSignal=0;
764 }
765 break;
766 }
767
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;
771 prevSignal=0;
772 break;
773 }
774
775 if(prevSignal>bunchData[i]){//means the peak of the signal has been reached and deconvolution will happen if the signal rise again.
776 signalFalling=kTRUE;
777 }
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];
783 }
784
785 prevSignal=bunchData[i];
786 time++;
787 indexInBunchData++;
788 }
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();
795 }
796 fRowPadVector[row][pad]->AddClusterCandidate(candidate);
797 if(indexInBunchData<fDigitReader->GetBunchSize()-1){
798 moreDataInBunch=kFALSE;
799 }
800 }while(moreDataInBunch);
8252a538 801 }
8252a538 802 }
803 }
b1c46961 804 }
8252a538 805}
806
807Bool_t AliHLTTPCClusterFinder::ComparePads(AliHLTTPCPad *nextPad,AliHLTTPCClusters* cluster,Int_t nextPadToRead){
808 //Checking if we have a match on the next pad
a74855c2 809 for(UInt_t candidateNumber=0;candidateNumber<nextPad->fClusterCandidates.size();candidateNumber++){
8252a538 810 AliHLTTPCClusters *candidate =&nextPad->fClusterCandidates[candidateNumber];
811 if(cluster->fMean-candidate->fMean==1 || candidate->fMean-cluster->fMean==1 || cluster->fMean-candidate->fMean==0){
6b15c309 812 if(fDeconvPad){
813 if(candidate->fTotalCharge<fTotalChargeOfPreviousClusterCandidate){//peak is reached
814 fChargeOfCandidatesFalling=kTRUE;
815 }
816 if(candidate->fTotalCharge>fTotalChargeOfPreviousClusterCandidate && fChargeOfCandidatesFalling==kTRUE){//we have deconvolution
817 return kFALSE;
818 }
819 }
8252a538 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;
6b15c309 827 if(candidate->fQMax>cluster->fQMax){
828 cluster->fQMax=candidate->fQMax;
829 }
830
2fdb1ae7 831 if(fDoPadSelection){
6b15c309 832 UInt_t rowNo = nextPad->GetRowNumber();
833 UInt_t padNo = nextPad->GetPadNumber();
834 if(padNo-1>0){
835 fRowPadVector[rowNo][padNo-2]->fSelectedPad=kTRUE;
836 fRowPadVector[rowNo][padNo-2]->fHWAddress=(AliHLTUInt16_t)fDigitReader->GetAltroBlockHWaddr(rowNo,padNo-2);
837 }
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);
2fdb1ae7 842 }
8252a538 843
844 //setting the matched pad to used
845 nextPad->fUsedClusterCandidates[candidateNumber]=1;
846 nextPadToRead++;
a74855c2 847 if(nextPadToRead<(Int_t)fNumberOfPadsInRow[fRowOfFirstCandidate]){
8252a538 848 nextPad=fRowPadVector[fRowOfFirstCandidate][nextPadToRead];
849 ComparePads(nextPad,cluster,nextPadToRead);
850 }
851 else{
852 return kFALSE;
853 }
854 }
855 else{
856 return kFALSE;
857 }
b1c46961 858 }
8252a538 859 return kFALSE;
01f43166 860}
64defa03 861
2fdb1ae7 862Int_t AliHLTTPCClusterFinder::FillHWAddressList(AliHLTUInt16_t *hwaddlist, Int_t maxHWadd){
863 Int_t counter=0;
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;
2fdb1ae7 869 counter++;
870 }
871 else{
872 HLTWarning("To many hardwareaddresses, skip adding");
873 }
874
875 }
876 }
877 }
878 return counter;
879}
880
64defa03 881void AliHLTTPCClusterFinder::FindClusters()
882{
b1c46961 883 // see header file for function documentation
8252a538 884
885 AliHLTTPCClusters* tmpCandidate=NULL;
a74855c2 886 for(UInt_t row=0;row<fNumberOfRows;row++){
8252a538 887 fRowOfFirstCandidate=row;
a74855c2 888 for(UInt_t pad=0;pad<fNumberOfPadsInRow[row]-1;pad++){
8252a538 889 AliHLTTPCPad *tmpPad=fRowPadVector[row][pad];
890 for(size_t candidate=0;candidate<tmpPad->fClusterCandidates.size();candidate++){
891 if(tmpPad->fUsedClusterCandidates[candidate]){
892 continue;
893 }
894 tmpCandidate=&tmpPad->fClusterCandidates[candidate];
895 UInt_t tmpTotalCharge=tmpCandidate->fTotalCharge;
6b15c309 896
8252a538 897 ComparePads(fRowPadVector[row][pad+1],tmpCandidate,pad+1);
898 if(tmpCandidate->fTotalCharge>tmpTotalCharge){
899 //we have a cluster
900 fClusters.push_back(*tmpCandidate);
901 }
902 }
368ff9d3 903 tmpPad->ClearCandidates();
8252a538 904 }
01f43166 905 }
8252a538 906
907 HLTInfo("Found %d clusters.",fClusters.size());
908
909 //TODO: Change so it stores AliHLTTPCSpacePointData directly, instead of this copying
910
911 AliClusterData * clusterlist = new AliClusterData[fClusters.size()]; //Clusterlist
912 for(unsigned int i=0;i<fClusters.size();i++){
913 clusterlist[i].fTotalCharge = fClusters[i].fTotalCharge;
914 clusterlist[i].fPad = fClusters[i].fPad;
915 clusterlist[i].fPad2 = fClusters[i].fPad2;
916 clusterlist[i].fTime = fClusters[i].fTime;
917 clusterlist[i].fTime2 = fClusters[i].fTime2;
918 clusterlist[i].fMean = fClusters[i].fMean;
919 clusterlist[i].fFlags = fClusters[i].fFlags;
920 clusterlist[i].fChargeFalling = fClusters[i].fChargeFalling;
921 clusterlist[i].fLastCharge = fClusters[i].fLastCharge;
922 clusterlist[i].fLastMergedPad = fClusters[i].fLastMergedPad;
923 clusterlist[i].fRow = fClusters[i].fRowNumber;
924 }
925 // PrintClusters();
926 WriteClusters(fClusters.size(),clusterlist);
e83e889b 927 delete [] clusterlist;
8252a538 928 fClusters.clear();
01f43166 929}
64defa03 930
8252a538 931void AliHLTTPCClusterFinder::PrintClusters()
932{
933 // see header file for class documentation
934 for(size_t i=0;i<fClusters.size();i++){
935 HLTInfo("Cluster number: %d",i);
6b15c309 936 HLTInfo("Row: %d \t Pad: %d",fClusters[i].fRowNumber,fClusters[i].fPad/fClusters[i].fTotalCharge);
8252a538 937 HLTInfo("Total Charge: %d",fClusters[i].fTotalCharge);
938 HLTInfo("fPad: %d",fClusters[i].fPad);
939 HLTInfo("PadError: %d",fClusters[i].fPad2);
6b15c309 940 HLTInfo("TimeMean: %d",fClusters[i].fTime/fClusters[i].fTotalCharge);
8252a538 941 HLTInfo("TimeError: %d",fClusters[i].fTime2);
942 HLTInfo("EndOfCluster:");
943 }
944}
945
01f43166 946void AliHLTTPCClusterFinder::WriteClusters(Int_t nclusters,AliHLTTPCClusters *list)//This is used when using the AliHLTTPCClusters class for cluster data
947{
948 //write cluster to output pointer
949 Int_t thisrow,thissector;
950 UInt_t counter = fNClusters;
951
952 for(int j=0; j<nclusters; j++)
953 {
954 if(!list[j].fFlags) continue; //discard single pad clusters
955 if(list[j].fTotalCharge < fThreshold) continue; //noise cluster
956
957 Float_t xyz[3];
958 Float_t fpad =(Float_t)list[j].fPad / list[j].fTotalCharge;
959 Float_t fpad2=fXYErr*fXYErr; //fixed given error
960 Float_t ftime =(Float_t)list[j].fTime / list[j].fTotalCharge;
961 Float_t ftime2=fZErr*fZErr; //fixed given error
962
d8b2f74a 963
01f43166 964 if(fCalcerr) { //calc the errors, otherwice take the fixed error
965 Int_t patch = AliHLTTPCTransform::GetPatch(fCurrentRow);
966 UInt_t q2=list[j].fTotalCharge*list[j].fTotalCharge;
967 Float_t sy2=list[j].fPad2 * list[j].fTotalCharge - list[j].fPad * list[j].fPad;
968 sy2/=q2;
969 if(sy2 < 0) {
970 LOG(AliHLTTPCLog::kError,"AliHLTTPCClusterFinder::WriteClusters","Cluster width")
971 <<"SigmaY2 negative "<<sy2<<" on row "<<fCurrentRow<<" "<<fpad<<" "<<ftime<<ENDLOG;
972 continue;
973 } else {
974 if(!fRawSP){
975 fpad2 = (sy2 + 1./12)*AliHLTTPCTransform::GetPadPitchWidth(patch)*AliHLTTPCTransform::GetPadPitchWidth(patch);
976 if(sy2 != 0){
977 fpad2*=0.108; //constants are from offline studies
978 if(patch<2)
979 fpad2*=2.07;
980 }
981 } else fpad2=sy2; //take the width not the error
982 }
983 Float_t sz2=list[j].fTime2*list[j].fTotalCharge - list[j].fTime*list[j].fTime;
984 sz2/=q2;
985 if(sz2 < 0){
986 LOG(AliHLTTPCLog::kError,"AliHLTTPCClusterFinder::WriteClusters","Cluster width")
987 <<"SigmaZ2 negative "<<sz2<<" on row "<<fCurrentRow<<" "<<fpad<<" "<<ftime<<ENDLOG;
988 continue;
989 } else {
990 if(!fRawSP){
991 ftime2 = (sz2 + 1./12)*AliHLTTPCTransform::GetZWidth()*AliHLTTPCTransform::GetZWidth();
992 if(sz2 != 0) {
993 ftime2 *= 0.169; //constants are from offline studies
994 if(patch<2)
995 ftime2 *= 1.77;
996 }
997 } else ftime2=sz2; //take the width, not the error
998 }
999 }
1000 if(fStdout==kTRUE)
8252a538 1001 HLTInfo("WriteCluster: padrow %d pad %d +- %d time +- %d charge %d",fCurrentRow, fpad, fpad2, ftime, ftime2, list[j].fTotalCharge);
1002
01f43166 1003 if(!fRawSP){
1004 AliHLTTPCTransform::Slice2Sector(fCurrentSlice,fCurrentRow,thissector,thisrow);
1005 AliHLTTPCTransform::Raw2Local(xyz,thissector,thisrow,fpad,ftime);
1006
1007 if(xyz[0]==0) LOG(AliHLTTPCLog::kError,"AliHLTTPCClustFinder","Cluster Finder")
1008 <<AliHLTTPCLog::kDec<<"Zero cluster"<<ENDLOG;
1009 if(fNClusters >= fMaxNClusters)
1010 {
1011 LOG(AliHLTTPCLog::kError,"AliHLTTPCClustFinder::WriteClusters","Cluster Finder")
1012 <<AliHLTTPCLog::kDec<<"Too many clusters "<<fNClusters<<ENDLOG;
1013 return;
1014 }
1015
1016 fSpacePointData[counter].fX = xyz[0];
6b15c309 1017 // fSpacePointData[counter].fY = xyz[1];
1018 if(fCurrentSlice<18){
1019 fSpacePointData[counter].fY = xyz[1];
1020 }
1021 else{
1022 fSpacePointData[counter].fY = -1*xyz[1];
1023 }
01f43166 1024 fSpacePointData[counter].fZ = xyz[2];
1025
1026 } else {
1027 fSpacePointData[counter].fX = fCurrentRow;
1028 fSpacePointData[counter].fY = fpad;
1029 fSpacePointData[counter].fZ = ftime;
1030 }
1031
1032 fSpacePointData[counter].fCharge = list[j].fTotalCharge;
1033 fSpacePointData[counter].fPadRow = fCurrentRow;
1034 fSpacePointData[counter].fSigmaY2 = fpad2;
1035 fSpacePointData[counter].fSigmaZ2 = ftime2;
1036
6b15c309 1037 fSpacePointData[counter].fMaxQ = list[j].fQMax;
1038
01f43166 1039 fSpacePointData[counter].fUsed = kFALSE; // only used / set in AliHLTTPCDisplay
1040 fSpacePointData[counter].fTrackN = -1; // only used / set in AliHLTTPCDisplay
1041
1042 Int_t patch=fCurrentPatch;
1043 if(patch==-1) patch=0; //never store negative patch number
1044 fSpacePointData[counter].fID = counter
1045 +((fCurrentSlice&0x7f)<<25)+((patch&0x7)<<22);//Uli
1046
1047#ifdef do_mc
1048 Int_t trackID[3];
1049 GetTrackID((Int_t)rint(fpad),(Int_t)rint(ftime),trackID);
1050
1051 fSpacePointData[counter].fTrackID[0] = trackID[0];
1052 fSpacePointData[counter].fTrackID[1] = trackID[1];
1053 fSpacePointData[counter].fTrackID[2] = trackID[2];
1054
01f43166 1055#endif
1056
1057 fNClusters++;
1058 counter++;
1059 }
1060}