Corrected bug, ClusterFinderUnpacked not cleaned properly. ClusterFinderUnpacked...
[u/mrichter/AliRoot.git] / HLT / TPCLib / AliHLTTPCClusterFinderComponent.cxx
1 // $Id$
2
3 //**************************************************************************
4 //* This file is property of and copyright by the ALICE HLT Project        * 
5 //* ALICE Experiment at CERN, All rights reserved.                         *
6 //*                                                                        *
7 //* Primary Authors: Timm Steinbeck, Matthias Richter                      *
8 //* Developers:      Kenneth Aamodt <kenneth.aamodt@student.uib.no>        *
9 //*                  for The ALICE HLT Project.                            *
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 //**************************************************************************
19
20 /** @file   AliHLTTPCClusterFinderComponent.cxx
21     @author Kenneth Aamodt <kenneth.aamodt@student.uib.no>
22     @date   
23     @brief  The TPC cluster finder processing component
24 */
25
26 #if __GNUC__>= 3
27 using namespace std;
28 #endif
29 #include "AliHLTTPCClusterFinderComponent.h"
30 #include "AliHLTTPCDigitReaderPacked.h"
31 #include "AliHLTTPCDigitReaderUnpacked.h"
32 #include "AliHLTTPCDigitReaderDecoder.h"
33 #include "AliHLTTPCClusterFinder.h"
34 #include "AliHLTTPCSpacePointData.h"
35 #include "AliHLTTPCClusterDataFormat.h"
36 #include "AliHLTTPCTransform.h"
37 #include "AliHLTTPCClusters.h"
38 #include "AliHLTTPCDefinitions.h"
39 #include "AliCDBEntry.h"
40 #include "AliCDBManager.h"
41
42 #include <cstdlib>
43 #include <cerrno>
44 #include "TString.h"
45 #include "TObjString.h"
46 #include <sys/time.h>
47
48 /** ROOT macro for the implementation of ROOT specific class methods */
49 ClassImp(AliHLTTPCClusterFinderComponent)
50
51 AliHLTTPCClusterFinderComponent::AliHLTTPCClusterFinderComponent(int mode)
52   :
53   fClusterFinder(NULL),
54   fReader(NULL),
55   fDeconvTime(kFALSE),
56   fDeconvPad(kFALSE),
57   fClusterDeconv(false),
58   fXYClusterError(-1),
59   fZClusterError(-1),
60   fModeSwitch(mode),
61   fUnsorted(1),
62   fPatch(0),
63   fGetActivePads(0),
64   fFirstTimeBin(-1),
65   fLastTimeBin(-1)
66 {
67   // see header file for class documentation
68   // or
69   // refer to README to build package
70   // or
71   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
72 }
73
74 AliHLTTPCClusterFinderComponent::~AliHLTTPCClusterFinderComponent()
75 {
76   // see header file for class documentation
77 }
78
79 // Public functions to implement AliHLTComponent's interface.
80 // These functions are required for the registration process
81
82 const char* AliHLTTPCClusterFinderComponent::GetComponentID()
83 {
84   // see header file for class documentation
85   switch(fModeSwitch){
86   case kClusterFinderPacked:
87     return "TPCClusterFinderPacked";
88     break;
89   case kClusterFinderUnpacked:   
90     return "TPCClusterFinderUnpacked";   
91     break;
92   case kClusterFinderDecoder:
93     return "TPCClusterFinderDecoder";
94     break;
95   }
96   HLTFatal("unknown digit reader type");
97   return "";
98 }
99
100 void AliHLTTPCClusterFinderComponent::GetInputDataTypes( vector<AliHLTComponentDataType>& list)
101 {
102   // see header file for class documentation
103   list.clear(); 
104   switch(fModeSwitch){
105   case kClusterFinderPacked:
106     list.push_back( kAliHLTDataTypeDDLRaw | kAliHLTDataOriginTPC );
107     break;
108   case kClusterFinderUnpacked:   
109     list.push_back( AliHLTTPCDefinitions::fgkUnpackedRawDataType );      
110     break;
111   case kClusterFinderDecoder:
112     list.push_back( kAliHLTDataTypeDDLRaw | kAliHLTDataOriginTPC );
113     break;
114   }
115 }
116
117 AliHLTComponentDataType AliHLTTPCClusterFinderComponent::GetOutputDataType()
118 {
119   // see header file for class documentation
120   return kAliHLTMultipleDataType;
121 }
122
123 int AliHLTTPCClusterFinderComponent::GetOutputDataTypes(AliHLTComponentDataTypeList& tgtList)
124
125 {
126   // see header file for class documentation
127   tgtList.clear();
128   tgtList.push_back(AliHLTTPCDefinitions::fgkClustersDataType);
129   tgtList.push_back(kAliHLTDataTypeHwAddr16);
130   return tgtList.size();
131 }
132
133 void AliHLTTPCClusterFinderComponent::GetOutputDataSize( unsigned long& constBase, double& inputMultiplier )
134 {
135   // see header file for class documentation
136   // XXX TODO: Find more realistic values.  
137   constBase = 0;
138   switch(fModeSwitch){
139   case 0:
140     inputMultiplier = (6 * 0.4);
141     break;
142   case 1:
143     inputMultiplier = 0.4;
144     break;
145   case 2:
146     inputMultiplier = (6 * 0.4);
147     break;
148   }
149 }
150
151 AliHLTComponent* AliHLTTPCClusterFinderComponent::Spawn()
152 {
153   // see header file for class documentation
154   return new AliHLTTPCClusterFinderComponent(fModeSwitch);
155 }
156         
157 int AliHLTTPCClusterFinderComponent::DoInit( int argc, const char** argv )
158 {
159   // see header file for class documentation
160   if ( fClusterFinder )
161     return EINPROGRESS;
162
163   fClusterFinder = new AliHLTTPCClusterFinder();
164
165   Float_t occulimit = 1.0;
166
167   Int_t i = 0;
168   Char_t* cpErr;
169
170   while ( i < argc ) {      
171
172     // -- deconvolute-time option
173     if ( !strcmp( argv[i], "-deconvolute-time" ) ) {
174       fDeconvTime = kTRUE;
175       i++;
176       continue;
177     }
178
179     // -- deconvolute-pad option
180     if ( !strcmp( argv[i], "-deconvolute-pad" ) ) {
181       fDeconvPad = kTRUE;
182       i++;
183       continue;
184     }
185
186     // -- number of timebins (default 1024)
187     if (!strcmp( argv[i], "-timebins") || !strcmp( argv[i], "timebins" )){
188       TString parameter(argv[i+1]);
189       parameter.Remove(TString::kLeading, ' '); // remove all blanks
190       if (parameter.IsDigit()) {
191         AliHLTTPCTransform::SetNTimeBins(parameter.Atoi());
192         HLTInfo("number of timebins set to %d, zbin=%f", AliHLTTPCTransform::GetNTimeBins(), AliHLTTPCTransform::GetZWidth());
193         fClusterFinder->UpdateLastTimeBin();
194       } else {
195         HLTError("Cannot timebin specifier '%s'.", argv[i+1]);
196         return EINVAL;
197       }
198       if(!strcmp( argv[i], "timebins")){
199         HLTWarning("Argument 'timebins' is old, please switch to new argument naming convention (-timebins). The timebins argument will still work, but please change anyway.");
200       }
201       i+=2;
202       continue;
203     }
204
205     // -first-timebin (default 0)
206     if ( !strcmp( argv[i], "-first-timebin" ) ) {
207       TString parameter(argv[i+1]);
208       parameter.Remove(TString::kLeading, ' '); // remove all blanks
209       if (parameter.IsDigit()){
210         fFirstTimeBin=parameter.Atoi();
211         HLTDebug("fFirstTimeBin set to %d",fFirstTimeBin);
212       } 
213       else {
214         HLTError("Cannot -first-timebin specifier '%s'. Not a number.", argv[i+1]);
215         return EINVAL;
216       }
217       i+=2;
218       continue;
219     }
220
221     // -last-timebin (default 1024)
222     if ( !strcmp( argv[i], "-last-timebin" ) ) {
223       TString parameter(argv[i+1]);
224       parameter.Remove(TString::kLeading, ' '); // remove all blanks
225       if (parameter.IsDigit()){
226         fLastTimeBin=parameter.Atoi();
227         HLTDebug("fLastTimeBin set to %d",fLastTimeBin);
228       } 
229       else {
230         HLTError("Cannot -last-timebin specifier '%s'. Not a number.", argv[i+1]);
231         return EINVAL;
232       }
233       i+=2;
234       continue;
235     }
236
237     // --  unsorted option
238     if ( !strcmp( argv[i], "-sorted" ) ) {
239       fUnsorted=0;
240       i++;
241       continue;
242     }
243
244       
245     // -- checking for active pads, used in 2007 December run
246     if ( !strcmp( argv[i], "-active-pads" ) || !strcmp( argv[i], "activepads" ) ) {
247       if(!strcmp( argv[i], "activepads" )){
248         HLTWarning("Please change to new component argument naming scheme and use '-active-pads' instead of 'active-pads'");
249       }
250       fGetActivePads = strtoul( argv[i+1], &cpErr ,0);
251       if ( *cpErr ){
252         HLTError("Cannot convert activepads specifier '%s'. Should  be 0(off) or 1(on), must be integer", argv[i+1]);
253         return EINVAL;
254       }
255       i+=2;
256       continue;
257     }
258
259     // -- pad occupancy limit
260     if ( !strcmp( argv[i], "-occupancy-limit" ) || !strcmp( argv[i], "occupancy-limit" ) ) {
261       if(!strcmp( argv[i], "occupancy-limit" )){
262         HLTWarning("Please switch to new component argument naming convention, use '-occupancy-limit' instead of 'occupancy-limit'");
263       }
264       occulimit = strtod( argv[i+1], &cpErr);
265       if ( *cpErr ) {
266         HLTError("Cannot convert occupancy specifier '%s'.", argv[i+1]);
267         return EINVAL;
268       }
269       if(fModeSwitch!=kClusterFinderPacked){
270         HLTWarning("Argument '-occupancy-limit' is only used with -sorted set and with the TPCClusterFinderPacked , argument is deprecated");
271       }
272       i+=2;
273       continue;
274     }
275
276     // -- raw reader mode option
277     if ( !strcmp( argv[i], "rawreadermode" ) ) {
278       if ( argc <= i+1 ) {
279         Logging( kHLTLogError, "HLT::TPCClusterFinder::DoInit", "Missing rawreadermode", "Raw Reader Mode not specified. rawreadermode is no longer a valid argument and will be deprecated even if rawreadermode is specified." );
280         return ENOTSUP;
281       }
282
283       HLTWarning("Argument 'rawreadermode' is deprecated");      
284
285       i += 2;
286       continue;
287     }
288
289     // -- pp-run option
290     if ( !strcmp( argv[i], "pp-run") ) {
291       HLTWarning("Argument 'pp-run' is obsolete, deconvolution is swiched off in both time and pad directions by default.");
292       fClusterDeconv = false;
293       i++;
294       continue;
295     }
296
297     // -- zero suppression threshold
298     if ( !strcmp( argv[i], "adc-threshold" ) ) {
299       strtoul( argv[i+1], &cpErr ,0);
300       if ( *cpErr ) {
301         HLTError("Cannot convert threshold specifier '%s'.", argv[i+1]);
302         return EINVAL;
303       }
304       HLTWarning("'adc-threshold' is no longer a valid argument, please use TPCZeroSuppression component if you want to zerosuppress data.");
305       i+=2;
306       continue;
307     }
308
309     // -- checking for rcu format
310     if ( !strcmp( argv[i], "oldrcuformat" ) ) {
311       strtoul( argv[i+1], &cpErr ,0);
312       if ( *cpErr ){
313         HLTError("Cannot convert oldrcuformat specifier '%s'. Should  be 0(off) or 1(on), must be integer", argv[i+1]);
314         return EINVAL;
315       }
316       HLTWarning("Argument 'oldrcuformat' is deprecated.");
317       i+=2;
318       continue;
319     }
320       
321     // -- checking for unsorted clusterfinding (default 1)
322     if ( !strcmp( argv[i], "unsorted" ) ) {
323       fUnsorted = strtoul( argv[i+1], &cpErr ,0);
324       if ( *cpErr ){
325         HLTError("Cannot convert unsorted specifier '%s'. Should  be 0(off) or 1(on), must be integer", argv[i+1]);
326         return EINVAL;
327       }
328       HLTWarning("Argument 'unsorted' is old and does not follow the new argument naming convention. A change has been made, and the clusterfinder will read the data unsorted by default. For sorted reading, please use '-sorted' as argument. (unsorted 0 will do the same job, but please change anyway.)");
329       i+=2;
330       continue;
331     }
332
333     // -- checking for nsigma-threshold, used in 2007 December run in ZeroSuppression
334     if ( !strcmp( argv[i], "nsigma-threshold" ) ) {
335       strtoul( argv[i+1], &cpErr ,0);
336       if ( *cpErr ){
337         HLTError("Cannot convert nsigma-threshold specifier '%s'. Must be integer", argv[i+1]);
338         return EINVAL;
339       }
340       i+=2;
341       HLTWarning("Argument 'nsigma-threshold' argument is obsolete.");
342       continue;
343     }
344
345     Logging(kHLTLogError, "HLT::TPCClusterFinder::DoInit", "Unknown Option", "Unknown option '%s'", argv[i] );
346     return EINVAL;
347
348   }
349
350   //Checking for conflicting arguments
351   if(fClusterDeconv){
352     if(fDeconvPad==kTRUE || fDeconvTime==kTRUE){
353       HLTWarning("Conflicting arguments: argument 'pp-run' will be ignored.");
354     }
355   }
356   if(occulimit!=1.0 && fUnsorted){
357     HLTWarning("Argument 'occupancy-limit' is deprecated when doing unsorted data reading.");
358   }
359   if(fGetActivePads==kTRUE && fUnsorted==kFALSE){
360     HLTWarning("Argument '-active-pads' only work with unsorted data reading. Active pads list will not be produced.");
361   }
362   
363
364   // Choose reader
365   if (fModeSwitch==kClusterFinderPacked) {
366       HLTDebug("using AliHLTTPCDigitReaderPacked");
367       fReader = new AliHLTTPCDigitReaderPacked();
368       if(fUnsorted==1){ fReader->SetUnsorted(kTRUE); }
369       fClusterFinder->SetReader(fReader);
370   }
371   else if(fModeSwitch==kClusterFinderDecoder){
372     HLTDebug("using AliHLTTPCDigitReaderDecoder");
373     fReader = new AliHLTTPCDigitReaderDecoder();
374     fClusterFinder->SetReader(fReader);
375   }
376   else{
377     HLTFatal("No mode set for clusterfindercomponent");
378   }
379   // if pp-run use occupancy limit else set to 1. ==> use all 
380   if ( !fClusterDeconv )
381     fClusterFinder->SetOccupancyLimit(occulimit);
382   else 
383     fClusterFinder->SetOccupancyLimit(1.0);
384       
385   
386   fClusterFinder->SetDeconv(fClusterDeconv);
387   fClusterFinder->SetDeconvPad(fDeconvPad);
388   fClusterFinder->SetDeconvTime(fDeconvPad);
389   fClusterFinder->SetXYError( fXYClusterError );
390   fClusterFinder->SetZError( fZClusterError );
391   if ( (fXYClusterError>0) && (fZClusterError>0) ){
392     fClusterFinder->SetCalcErr( false );
393   }
394
395   if(fFirstTimeBin>0){
396     fClusterFinder->SetFirstTimeBin(fFirstTimeBin);
397   }
398   if(fLastTimeBin>0 && fLastTimeBin>fFirstTimeBin && fLastTimeBin<=AliHLTTPCTransform::GetNTimeBins()){
399     fClusterFinder->SetLastTimeBin(fLastTimeBin);
400   }
401
402   return 0;
403 }
404
405 int AliHLTTPCClusterFinderComponent::DoDeinit()
406 {
407   // see header file for class documentation
408
409   if ( fClusterFinder )
410     delete fClusterFinder;
411   fClusterFinder = NULL;
412  
413   if ( fReader )
414     delete fReader;
415   fReader = NULL;
416     
417   return 0;
418 }
419
420 int AliHLTTPCClusterFinderComponent::DoEvent( const AliHLTComponentEventData& evtData, 
421                                               const AliHLTComponentBlockData* blocks, 
422                                               AliHLTComponentTriggerData& /*trigData*/, AliHLTUInt8_t* outputPtr, 
423                                               AliHLTUInt32_t& size, 
424                                               vector<AliHLTComponentBlockData>& outputBlocks )
425 {
426   // see header file for class documentation
427
428   if(fReader == NULL){
429     HLTFatal("Digit reader not initialized, aborting event.");
430     size=0;
431     return 0;    
432   }
433
434   if(GetFirstInputBlock( kAliHLTDataTypeSOR ) || GetFirstInputBlock( kAliHLTDataTypeEOR )){
435     size=0;
436     return 0;
437   }
438
439   //  == init iter (pointer to datablock)
440   const AliHLTComponentBlockData* iter = NULL;
441   unsigned long ndx;
442
443   //  == OUTdatatype pointer
444   AliHLTTPCClusterData* outPtr;
445
446   AliHLTUInt8_t* outBPtr;
447   UInt_t offset, mysize, nSize, tSize = 0;
448
449   outBPtr = outputPtr;
450   outPtr = (AliHLTTPCClusterData*)outBPtr;
451
452   Int_t slice, patch;
453   unsigned long maxPoints, realPoints = 0;
454
455   for ( ndx = 0; ndx < evtData.fBlockCnt; ndx++ )
456     {
457       iter = blocks+ndx;
458       mysize = 0;
459       offset = tSize;
460
461
462       if (fModeSwitch==0 || fModeSwitch==2) {
463         HLTDebug("Event 0x%08LX (%Lu) received datatype: %s - required datatype: %s",
464                  evtData.fEventID, evtData.fEventID, 
465                  DataType2Text( iter->fDataType).c_str(), 
466                  DataType2Text(kAliHLTDataTypeDDLRaw | kAliHLTDataOriginTPC).c_str());
467
468         if (iter->fDataType == AliHLTTPCDefinitions::fgkDDLPackedRawDataType &&
469             GetEventCount()<2) {
470           HLTWarning("data type %s is depricated, use %s (kAliHLTDataTypeDDLRaw)!",
471                      DataType2Text(AliHLTTPCDefinitions::fgkDDLPackedRawDataType).c_str(),
472                      DataType2Text(kAliHLTDataTypeDDLRaw | kAliHLTDataOriginTPC).c_str());
473           }
474
475         if ( iter->fDataType != (kAliHLTDataTypeDDLRaw | kAliHLTDataOriginTPC) &&
476              iter->fDataType != AliHLTTPCDefinitions::fgkDDLPackedRawDataType ) continue;
477
478       }
479       else if(fModeSwitch==1){
480         HLTWarning("Unpacked data type depreciated, block aborted");
481         HLTDebug("Event 0x%08LX (%Lu) received datatype: %s - required datatype: %s",
482                  evtData.fEventID, evtData.fEventID, 
483                  DataType2Text( iter->fDataType).c_str(), 
484                  DataType2Text(AliHLTTPCDefinitions::fgkUnpackedRawDataType).c_str());
485         continue;
486       }
487
488       slice = AliHLTTPCDefinitions::GetMinSliceNr( *iter );
489       patch = AliHLTTPCDefinitions::GetMinPatchNr( *iter );
490
491       if(fUnsorted){
492         fClusterFinder->SetUnsorted(fUnsorted);
493         fClusterFinder->SetPatch(patch);
494       }
495
496       outPtr = (AliHLTTPCClusterData*)outBPtr;
497
498       maxPoints = (size-tSize-sizeof(AliHLTTPCClusterData))/sizeof(AliHLTTPCSpacePointData);
499
500       fClusterFinder->InitSlice( slice, patch, maxPoints );
501       fClusterFinder->SetOutputArray( (AliHLTTPCSpacePointData*)outPtr->fSpacePoints );
502         
503       if(fUnsorted){
504         if(fGetActivePads){
505           fClusterFinder->SetDoPadSelection(kTRUE);
506         }       
507         if(fDeconvTime){
508           fClusterFinder->ReadDataUnsortedDeconvoluteTime(iter->fPtr, iter->fSize);
509         }
510         else{
511           fClusterFinder->ReadDataUnsorted(iter->fPtr, iter->fSize);
512         }
513
514         fClusterFinder->FindClusters();
515       }
516       else{
517         fClusterFinder->Read(iter->fPtr, iter->fSize );
518         fClusterFinder->ProcessDigits();
519       }
520
521       realPoints = fClusterFinder->GetNumberOfClusters();
522         
523       outPtr->fSpacePointCnt = realPoints;
524       nSize = sizeof(AliHLTTPCSpacePointData)*realPoints;
525       mysize += nSize+sizeof(AliHLTTPCClusterData);
526
527       Logging( kHLTLogDebug, "HLT::TPCClusterFinder::DoEvent", "Spacepoints", 
528                "Number of spacepoints: %lu Slice/Patch/RowMin/RowMax: %d/%d/%d/%d.",
529                realPoints, slice, patch,AliHLTTPCTransform::GetFirstRow( patch ) , AliHLTTPCTransform::GetLastRow( patch ) );
530       AliHLTComponentBlockData bd;
531       FillBlockData( bd );
532       bd.fOffset = offset;
533       bd.fSize = mysize;
534       bd.fSpecification = iter->fSpecification;
535       bd.fDataType = AliHLTTPCDefinitions::fgkClustersDataType;
536       outputBlocks.push_back( bd );
537         
538       tSize += mysize;
539       outBPtr += mysize;
540       outPtr = (AliHLTTPCClusterData*)outBPtr;
541         
542
543       if ( tSize > size )
544         {
545           Logging( kHLTLogFatal, "HLT::TPCClusterFinder::DoEvent", "Too much data", 
546                    "Data written over allowed buffer. Amount written: %lu, allowed amount: %lu.",
547                    tSize, size );
548           return -ENOSPC;
549         }
550         
551       if(fUnsorted && fGetActivePads){
552        Int_t maxNumberOfHW=(Int_t)((size-tSize)/sizeof(AliHLTUInt16_t)-1);
553        AliHLTUInt16_t* outputHWPtr= (AliHLTUInt16_t*)(outputPtr+tSize);
554        Int_t nHWAdd = fClusterFinder->FillHWAddressList(outputHWPtr, maxNumberOfHW);
555       
556        //cout<<"Number of hardwareaddresses: "<<nHWAdd<<endl;
557        for(AliHLTUInt16_t test=0;test<nHWAdd;test++){
558          //cout<<"The HW address is: "<<(AliHLTUInt16_t)outputHWPtr[test]<<endl;
559        }
560        AliHLTComponentBlockData bdHW;
561        FillBlockData( bdHW );
562        bdHW.fOffset = tSize ;
563        bdHW.fSize = nHWAdd*sizeof(AliHLTUInt16_t);
564        bdHW.fSpecification = iter->fSpecification;
565        bdHW.fDataType = kAliHLTDataTypeHwAddr16;
566        outputBlocks.push_back( bdHW );
567        
568        tSize+=nHWAdd*sizeof(AliHLTUInt16_t);
569       }
570       fReader->Reset();
571     }
572     
573   size = tSize;
574
575   return 0;
576 }
577
578 int AliHLTTPCClusterFinderComponent::Reconfigure(const char* cdbEntry, const char* chainId)
579 {
580   // see header file for class documentation
581   const char* path="HLT/ConfigTPC";
582   if (cdbEntry) path=cdbEntry;
583   if (path) {
584     HLTInfo("reconfigure from entry %s, chain id %s", path, (chainId!=NULL && chainId[0]!=0)?chainId:"<none>");
585     AliCDBEntry *pEntry = AliCDBManager::Instance()->Get(path/*,GetRunNo()*/);
586     if (pEntry) {
587       TObjString* pString=dynamic_cast<TObjString*>(pEntry->GetObject());
588       if (pString) {
589         HLTInfo("received configuration object: %s", pString->GetString().Data());
590       } else {
591         HLTError("configuration object \"%s\" has wrong type, required TObjString", path);
592       }
593     } else {
594       HLTError("can not fetch object \"%s\" from CDB", path);
595     }
596   }
597   return 0;
598 }