]> git.uio.no Git - u/mrichter/AliRoot.git/blame - HLT/TPCLib/AliHLTTPCClusterFinder.cxx
Adding a cut on ADC to speed up things (Dieggo)
[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();
70a4e20c 781 if(row==1000||pad==1000){
782 HLTInfo("Corrupt data, hw address exceeded the maximum amount");
783 continue;
784 }
785
8252a538 786 fRowPadVector[row][pad]->ClearCandidates();
787 while(fDigitReader->NextBunch()){
788 if(fDigitReader->GetBunchSize()>1){//to remove single timebin values, this will have to change at some point
789 const UInt_t *bunchData= fDigitReader->GetSignals();
790 UInt_t time = fDigitReader->GetTime();
791 AliHLTTPCClusters candidate;
792 for(Int_t i=0;i<fDigitReader->GetBunchSize();i++){
793 candidate.fTotalCharge+=bunchData[i];
794 candidate.fTime += time*bunchData[i];
795 candidate.fTime2 += time*time*bunchData[i];
796 time++;
797 }
798 if(candidate.fTotalCharge>0){
799 candidate.fMean=candidate.fTime/candidate.fTotalCharge;
800 candidate.fPad=candidate.fTotalCharge*pad;
801 candidate.fPad2=candidate.fPad*pad;
802 candidate.fLastMergedPad=pad;
803 candidate.fRowNumber=row;
804 }
805 fRowPadVector[row][pad]->AddClusterCandidate(candidate);
806 }
807 }
b1c46961 808 }
8252a538 809}
810
811Bool_t AliHLTTPCClusterFinder::ComparePads(AliHLTTPCPad *nextPad,AliHLTTPCClusters* cluster,Int_t nextPadToRead){
812 //Checking if we have a match on the next pad
813 for(Int_t candidateNumber=0;candidateNumber<nextPad->fClusterCandidates.size();candidateNumber++){
814 AliHLTTPCClusters *candidate =&nextPad->fClusterCandidates[candidateNumber];
815 if(cluster->fMean-candidate->fMean==1 || candidate->fMean-cluster->fMean==1 || cluster->fMean-candidate->fMean==0){
816 cluster->fMean=candidate->fMean;
817 cluster->fTotalCharge+=candidate->fTotalCharge;
818 cluster->fTime += candidate->fTime;
819 cluster->fTime2 += candidate->fTime2;
820 cluster->fPad+=candidate->fPad;
821 cluster->fPad2=candidate->fPad2;
822 cluster->fLastMergedPad=candidate->fPad;
823
824 //setting the matched pad to used
825 nextPad->fUsedClusterCandidates[candidateNumber]=1;
826 nextPadToRead++;
827 if(nextPadToRead<fNumberOfPadsInRow[fRowOfFirstCandidate]){
828 nextPad=fRowPadVector[fRowOfFirstCandidate][nextPadToRead];
829 ComparePads(nextPad,cluster,nextPadToRead);
830 }
831 else{
832 return kFALSE;
833 }
834 }
835 else{
836 return kFALSE;
837 }
b1c46961 838 }
8252a538 839 return kFALSE;
01f43166 840}
64defa03 841
842void AliHLTTPCClusterFinder::FindClusters()
843{
b1c46961 844 // see header file for function documentation
8252a538 845
846 AliHLTTPCClusters* tmpCandidate=NULL;
847 for(Int_t row=0;row<fNumberOfRows;row++){
848 fRowOfFirstCandidate=row;
849 for(Int_t pad=0;pad<fNumberOfPadsInRow[row]-1;pad++){
850 AliHLTTPCPad *tmpPad=fRowPadVector[row][pad];
851 for(size_t candidate=0;candidate<tmpPad->fClusterCandidates.size();candidate++){
852 if(tmpPad->fUsedClusterCandidates[candidate]){
853 continue;
854 }
855 tmpCandidate=&tmpPad->fClusterCandidates[candidate];
856 UInt_t tmpTotalCharge=tmpCandidate->fTotalCharge;
857 ComparePads(fRowPadVector[row][pad+1],tmpCandidate,pad+1);
858 if(tmpCandidate->fTotalCharge>tmpTotalCharge){
859 //we have a cluster
860 fClusters.push_back(*tmpCandidate);
861 }
862 }
863 }
01f43166 864 }
8252a538 865
866 HLTInfo("Found %d clusters.",fClusters.size());
867
868 //TODO: Change so it stores AliHLTTPCSpacePointData directly, instead of this copying
869
870 AliClusterData * clusterlist = new AliClusterData[fClusters.size()]; //Clusterlist
871 for(unsigned int i=0;i<fClusters.size();i++){
872 clusterlist[i].fTotalCharge = fClusters[i].fTotalCharge;
873 clusterlist[i].fPad = fClusters[i].fPad;
874 clusterlist[i].fPad2 = fClusters[i].fPad2;
875 clusterlist[i].fTime = fClusters[i].fTime;
876 clusterlist[i].fTime2 = fClusters[i].fTime2;
877 clusterlist[i].fMean = fClusters[i].fMean;
878 clusterlist[i].fFlags = fClusters[i].fFlags;
879 clusterlist[i].fChargeFalling = fClusters[i].fChargeFalling;
880 clusterlist[i].fLastCharge = fClusters[i].fLastCharge;
881 clusterlist[i].fLastMergedPad = fClusters[i].fLastMergedPad;
882 clusterlist[i].fRow = fClusters[i].fRowNumber;
883 }
884 // PrintClusters();
885 WriteClusters(fClusters.size(),clusterlist);
e83e889b 886 delete [] clusterlist;
8252a538 887 fClusters.clear();
01f43166 888}
64defa03 889
8252a538 890void AliHLTTPCClusterFinder::PrintClusters()
891{
892 // see header file for class documentation
893 for(size_t i=0;i<fClusters.size();i++){
894 HLTInfo("Cluster number: %d",i);
895 HLTInfo("Row: %d \t Pad: %d",fClusters[i].fRowNumber,fClusters[i].fFirstPad);
896 HLTInfo("Total Charge: %d",fClusters[i].fTotalCharge);
897 HLTInfo("fPad: %d",fClusters[i].fPad);
898 HLTInfo("PadError: %d",fClusters[i].fPad2);
899 HLTInfo("TimeMean: %d",fClusters[i].fTime);
900 HLTInfo("TimeError: %d",fClusters[i].fTime2);
901 HLTInfo("EndOfCluster:");
902 }
903}
904
905/*
906
64defa03 907Int_t AliHLTTPCClusterFinder::GetActivePads(AliHLTTPCPadArray::AliHLTTPCActivePads* activePads,Int_t maxActivePads)
908{
b1c46961 909 // see header file for function documentation
64defa03 910 Int_t iResult=0;
911 if (fPadArray) {
912 iResult=fPadArray->GetActivePads((AliHLTTPCPadArray::AliHLTTPCActivePads*)activePads , maxActivePads);
913 } else if ((iResult=fActivePads.size())>0) {
914 if (iResult>maxActivePads) {
915 HLTWarning("target array (%d) not big enough to receive %d active pad descriptors", maxActivePads, iResult);
916 iResult=maxActivePads;
917 }
918 memcpy(activePads, &fActivePads[0], iResult*sizeof(AliHLTTPCPadArray::AliHLTTPCActivePads));
919 }
920
921 return iResult;
b1c46961 922}
8252a538 923*/
01f43166 924void AliHLTTPCClusterFinder::WriteClusters(Int_t nclusters,AliHLTTPCClusters *list)//This is used when using the AliHLTTPCClusters class for cluster data
925{
926 //write cluster to output pointer
927 Int_t thisrow,thissector;
928 UInt_t counter = fNClusters;
929
930 for(int j=0; j<nclusters; j++)
931 {
932 if(!list[j].fFlags) continue; //discard single pad clusters
933 if(list[j].fTotalCharge < fThreshold) continue; //noise cluster
934
935 Float_t xyz[3];
936 Float_t fpad =(Float_t)list[j].fPad / list[j].fTotalCharge;
937 Float_t fpad2=fXYErr*fXYErr; //fixed given error
938 Float_t ftime =(Float_t)list[j].fTime / list[j].fTotalCharge;
939 Float_t ftime2=fZErr*fZErr; //fixed given error
940
d8b2f74a 941
01f43166 942 if(fCalcerr) { //calc the errors, otherwice take the fixed error
943 Int_t patch = AliHLTTPCTransform::GetPatch(fCurrentRow);
944 UInt_t q2=list[j].fTotalCharge*list[j].fTotalCharge;
945 Float_t sy2=list[j].fPad2 * list[j].fTotalCharge - list[j].fPad * list[j].fPad;
946 sy2/=q2;
947 if(sy2 < 0) {
948 LOG(AliHLTTPCLog::kError,"AliHLTTPCClusterFinder::WriteClusters","Cluster width")
949 <<"SigmaY2 negative "<<sy2<<" on row "<<fCurrentRow<<" "<<fpad<<" "<<ftime<<ENDLOG;
950 continue;
951 } else {
952 if(!fRawSP){
953 fpad2 = (sy2 + 1./12)*AliHLTTPCTransform::GetPadPitchWidth(patch)*AliHLTTPCTransform::GetPadPitchWidth(patch);
954 if(sy2 != 0){
955 fpad2*=0.108; //constants are from offline studies
956 if(patch<2)
957 fpad2*=2.07;
958 }
959 } else fpad2=sy2; //take the width not the error
960 }
961 Float_t sz2=list[j].fTime2*list[j].fTotalCharge - list[j].fTime*list[j].fTime;
962 sz2/=q2;
963 if(sz2 < 0){
964 LOG(AliHLTTPCLog::kError,"AliHLTTPCClusterFinder::WriteClusters","Cluster width")
965 <<"SigmaZ2 negative "<<sz2<<" on row "<<fCurrentRow<<" "<<fpad<<" "<<ftime<<ENDLOG;
966 continue;
967 } else {
968 if(!fRawSP){
969 ftime2 = (sz2 + 1./12)*AliHLTTPCTransform::GetZWidth()*AliHLTTPCTransform::GetZWidth();
970 if(sz2 != 0) {
971 ftime2 *= 0.169; //constants are from offline studies
972 if(patch<2)
973 ftime2 *= 1.77;
974 }
975 } else ftime2=sz2; //take the width, not the error
976 }
977 }
978 if(fStdout==kTRUE)
8252a538 979 HLTInfo("WriteCluster: padrow %d pad %d +- %d time +- %d charge %d",fCurrentRow, fpad, fpad2, ftime, ftime2, list[j].fTotalCharge);
980
01f43166 981 if(!fRawSP){
982 AliHLTTPCTransform::Slice2Sector(fCurrentSlice,fCurrentRow,thissector,thisrow);
983 AliHLTTPCTransform::Raw2Local(xyz,thissector,thisrow,fpad,ftime);
984
985 if(xyz[0]==0) LOG(AliHLTTPCLog::kError,"AliHLTTPCClustFinder","Cluster Finder")
986 <<AliHLTTPCLog::kDec<<"Zero cluster"<<ENDLOG;
987 if(fNClusters >= fMaxNClusters)
988 {
989 LOG(AliHLTTPCLog::kError,"AliHLTTPCClustFinder::WriteClusters","Cluster Finder")
990 <<AliHLTTPCLog::kDec<<"Too many clusters "<<fNClusters<<ENDLOG;
991 return;
992 }
993
994 fSpacePointData[counter].fX = xyz[0];
995 fSpacePointData[counter].fY = xyz[1];
996 fSpacePointData[counter].fZ = xyz[2];
997
998 } else {
999 fSpacePointData[counter].fX = fCurrentRow;
1000 fSpacePointData[counter].fY = fpad;
1001 fSpacePointData[counter].fZ = ftime;
1002 }
1003
1004 fSpacePointData[counter].fCharge = list[j].fTotalCharge;
1005 fSpacePointData[counter].fPadRow = fCurrentRow;
1006 fSpacePointData[counter].fSigmaY2 = fpad2;
1007 fSpacePointData[counter].fSigmaZ2 = ftime2;
1008
1009 fSpacePointData[counter].fUsed = kFALSE; // only used / set in AliHLTTPCDisplay
1010 fSpacePointData[counter].fTrackN = -1; // only used / set in AliHLTTPCDisplay
1011
1012 Int_t patch=fCurrentPatch;
1013 if(patch==-1) patch=0; //never store negative patch number
1014 fSpacePointData[counter].fID = counter
1015 +((fCurrentSlice&0x7f)<<25)+((patch&0x7)<<22);//Uli
1016
1017#ifdef do_mc
1018 Int_t trackID[3];
1019 GetTrackID((Int_t)rint(fpad),(Int_t)rint(ftime),trackID);
1020
1021 fSpacePointData[counter].fTrackID[0] = trackID[0];
1022 fSpacePointData[counter].fTrackID[1] = trackID[1];
1023 fSpacePointData[counter].fTrackID[2] = trackID[2];
1024
01f43166 1025#endif
1026
1027 fNClusters++;
1028 counter++;
1029 }
1030}