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