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