added Huffman compression stuff for ALTRO data (Jenny)
[u/mrichter/AliRoot.git] / HLT / comp / AliHLTCOMPHuffmanAltroComponent.cxx
1 // $Id$
2
3 /**************************************************************************
4  * This file is property of and copyright by the ALICE HLT Project        * 
5  * All rights reserved.                                                   *
6  *                                                                        *
7  * Primary Author: Jenny Wagner  (jwagner@cern.ch)                        *
8  *                                                                        *
9  * Permission to use, copy, modify and distribute this software and its   *
10  * documentation strictly for non-commercial purposes is hereby granted   *
11  * without fee, provided that the above copyright notice appears in all   *
12  * copies and that both the copyright notice and this permission notice   *
13  * appear in the supporting documentation. The authors make no claims     *
14  * about the suitability of this software for any purpose. It is          * 
15  * provided "as is" without express or implied warranty.                  *
16  **************************************************************************/
17
18 /** @file   AliHLTCOMPHuffmanAltroComponent.cxx
19     @author Jenny Wagner
20     @date   29-08-2007
21     @brief  The Huffman compressor component.
22 */
23
24 #if __GNUC__>= 3
25 using namespace std;
26 #endif
27
28 #include "AliHLTCOMPHuffmanAltroComponent.h"
29 #include "AliHLTCOMPHuffmanAltro.h"
30 #include "AliHLTCOMPHuffmanData.h"
31 #include "AliHLTCompDefinitions.h"
32 #include "AliHLTStdIncludes.h"
33 #include "TFile.h"
34
35 ClassImp(AliHLTCOMPHuffmanAltroComponent)
36
37 /* constructur with arguments */
38 AliHLTCOMPHuffmanAltroComponent::AliHLTCOMPHuffmanAltroComponent(bool compression)
39   :
40   fHuffmanCompressor(NULL),
41   fCompressionSwitch(compression),
42   fTrainingMode(kFALSE),
43   fHuffmanData(NULL),
44   fOrigin(kAliHLTVoidDataOrigin),
45   fRunNumber(0),
46   fDataSpec(0),
47   fTablePath(),
48   fNrcuTrailerwords(0)
49  
50 {
51    // see header file for class documentation
52   // or
53   // refer to README to build package
54   // or
55   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
56 }
57
58 AliHLTCOMPHuffmanAltroComponent::~AliHLTCOMPHuffmanAltroComponent()
59 {
60   // see header file for class documentation
61 }
62
63 // Public functions to implement AliHLTComponent's interface.
64 // These functions are required for the registration process
65
66 const char* AliHLTCOMPHuffmanAltroComponent::GetComponentID()
67 {
68   // see header file for class documentation
69   if(fCompressionSwitch)
70     {
71       return "COMPHuffmanCompressor";
72     }
73   else
74     {
75       return "COMPHuffmanDecompressor";
76     }
77 }
78
79 void AliHLTCOMPHuffmanAltroComponent::GetInputDataTypes( vector<AliHLTComponentDataType>& list)
80 {
81   // see header file for class documentation
82   // initialise list
83   list.clear(); 
84
85   // if compression is to be done, input data is packed raw data
86   // else (decompression): input data is special entropy encoded raw data
87   if (fCompressionSwitch) list.push_back( kAliHLTDataTypeDDLRaw );
88   else list.push_back( AliHLTCompDefinitions::fgkDDLEncodedHuffmanAltroDataType);
89   
90 }
91
92 AliHLTComponentDataType AliHLTCOMPHuffmanAltroComponent::GetOutputDataType()
93 {
94   // see header file for class documentation
95   // if compression is to be one, output data is special entropy encoded raw data
96   // else (decompression): output data is packed raw data
97   AliHLTComponentDataType dt=kAliHLTDataTypeDDLRaw;
98   if(fCompressionSwitch)
99     dt=AliHLTCompDefinitions::fgkDDLEncodedHuffmanAltroDataType;
100   if (!fOrigin.IsNull()) SetDataType(dt, NULL, fOrigin.Data());
101   return dt;
102 }
103
104 void AliHLTCOMPHuffmanAltroComponent::GetOutputDataSize(unsigned long& constBase, double& inputMultiplier )
105 {
106   // see header file for class documentation
107   // reserved outputsize = inputside * inputMultiplier
108   constBase = 0;
109   if (fCompressionSwitch == kFALSE)
110     {
111       // for decompression: compressed * 4 = (enough space for) decompressed
112       inputMultiplier = 4.0 ;
113     }
114   else
115     {
116       // for compression: original * 1 = (enough space for) compressed
117       inputMultiplier = 1.0;
118     }
119 }
120
121 AliHLTComponent* AliHLTCOMPHuffmanAltroComponent::Spawn()
122 {
123   // see header file for class documentation
124   return new AliHLTCOMPHuffmanAltroComponent(fCompressionSwitch);
125 }
126
127
128 int AliHLTCOMPHuffmanAltroComponent::DoInit( int argc, const char** argv )
129 {
130   
131   // see header file for class documentation
132   
133   if ( fHuffmanCompressor )
134     return EINPROGRESS;
135   
136   
137   Int_t i = 0;
138   Char_t* cpErr;
139   
140   while ( i < argc ) 
141     {     
142       // -- training mode wrongly called here
143       if ( !strcmp( argv[i], "-training" ) ) 
144         {
145           fTrainingMode = kTRUE;
146           
147           HLTInfo("HuffmanCompressor called in training mode, please call HuffmanCalibration instead.");
148
149           return EINVAL;
150         }
151       
152       // mode option: compress or decompress
153       //  if ( !strcmp( argv[i], "-compress" ) ) 
154       //        {
155       //          fCompressionSwitch = kTRUE;
156
157       //  ++i;
158       //  continue;
159           //}
160     
161       //if(!strcmp( argv[i], "-decompress" ) ) 
162       //        {
163       //          fCompressionSwitch = kFALSE;
164           
165       //          ++i;
166       //  continue;
167       //        }
168    
169       // -- argument to load correct code table for respective data specifications (origin, runnumber, specification)
170       if ( !strcmp( argv[i], "-origin" ) ) 
171         {
172          
173           if ( argc <= i+1 ) 
174             {
175               HLTError("Missing data origin specification");
176               return ENOTSUP;
177             }
178
179           // get data origin (TPC, PHOS, ITS...)
180           fOrigin=argv[i+1];
181
182           HLTDebug("Origin is set to %s.", fOrigin.Data());
183           
184           // validation checker
185           
186           i += 2;
187           continue;
188         }
189
190       // -- get run number specification
191       if ( !strcmp( argv[i], "-runnumber" ) ) 
192         {
193           if ( argc <= i+1 ) 
194             {
195               HLTError("Missing run number specification");
196               return ENOTSUP;
197             }
198
199           // get run number
200           const char* runnumber = argv[i+1];
201           
202           fRunNumber =  atoi(runnumber);
203
204           HLTDebug("Run number set to %d (Dec) = %X (Hex).", fRunNumber, fRunNumber);
205           
206           // validation check of run number?!
207
208           i += 2;
209           continue;
210         }
211
212
213       // -- get data specification (e.g. TPC: slice and patch information contained in "dataspec")
214       if ( !strcmp( argv[i], "-dataspec" ) ) 
215         {
216           if ( argc <= i+1 ) 
217             {
218               HLTError("Missing data specification");
219               return ENOTSUP;
220             }
221
222           // get data spec
223           fDataSpec = strtoul(argv[i+1], NULL, 16);
224
225           HLTDebug("Dataspecification set to %d (Dec) = %08X (Hex).", fDataSpec, fDataSpec);
226           
227           // validation check of specification?!
228
229           i += 2;
230           continue;
231         }
232
233       // -- get tablepathname (e.g. ../HLT-data/)
234       if ( !strcmp( argv[i], "-tablepath" ) ) 
235         {
236           if ( argc <= i+1 ) 
237             {
238               HLTDebug("Missing table path argument.");
239             }
240
241           // get data spec
242           fTablePath=argv[i+1];
243
244           HLTDebug("Table path set to %s.", fTablePath.Data());
245           
246           // validation check of specification?!
247
248           i += 2;
249           continue;
250         }
251
252       // -- number of trailerwords: from 1 to 3
253       if ( !strcmp( argv[i], "-trailerwords" ) ) 
254         {
255           if ( argc <= i+1 ) 
256             {
257               HLTError("Missing trailerword specification");
258               return ENOTSUP;
259             }
260           
261           if ( !strcmp( argv[i+1], "1" ) ) 
262               fNrcuTrailerwords = 1;
263           else if ( !strcmp( argv[i+1], "2" ) ) 
264             fNrcuTrailerwords = 2; 
265           else if ( !strcmp( argv[i+1], "3" ) ) 
266             fNrcuTrailerwords = 3; 
267           else
268             {
269               HLTError("Missing number of trailerwords, cannot accept argument '%s'.", argv[i+1] );
270               
271               return EINVAL;
272             }   
273           
274           i += 2;
275           continue;
276         }
277             
278       HLTError("Unknown Option '%s'", argv[i] );
279       return EINVAL;
280     } // end while-loop
281   
282   // load HuffmanData from root-file to acquire translation table
283   fHuffmanData = new AliHLTCOMPHuffmanData();
284
285   TString rootfilename;
286   if(fTablePath.IsNull())
287     {
288       // if no table path is explicity set, take current path as table path
289       rootfilename.Form("huffmanData_%s_%08X_%08X.root", fOrigin.Data(), fRunNumber, fDataSpec);   
290     }
291   else
292     {
293       rootfilename.Form("%shuffmanData_%s_%08X_%08X.root", fTablePath.Data(), fOrigin.Data(), fRunNumber, fDataSpec);
294     }
295
296   TFile* huffmancodefile = new TFile(rootfilename, "READ");
297   
298   if(huffmancodefile->IsZombie())
299   { 
300     HLTFatal("No Huffman code table available for %s.", rootfilename.Data());
301       return EINVAL;
302     }    
303   fHuffmanData = (AliHLTCOMPHuffmanData*) huffmancodefile->Get("HuffmanData");
304
305   // create a new Huffman compressor 
306   fHuffmanCompressor = new AliHLTCOMPHuffmanAltro(fCompressionSwitch, kFALSE, NULL, fNrcuTrailerwords);
307   
308   // get translation table for pure encoding and decoding from HuffmanData
309   fHuffmanCompressor->GetTranslationTable(fHuffmanData);
310     
311   return 0;
312 }
313
314 int AliHLTCOMPHuffmanAltroComponent::DoDeinit()
315 {
316
317   // see header file for class documentation
318   if (fHuffmanCompressor) 
319     delete fHuffmanCompressor;
320   fHuffmanCompressor = NULL;
321
322   if ( fHuffmanData )
323     delete fHuffmanData; 
324   fHuffmanData = NULL;
325   
326   return 0;
327 }
328
329 int AliHLTCOMPHuffmanAltroComponent::DoEvent( const AliHLTComponentEventData& evtData, 
330                                               const AliHLTComponentBlockData* blocks, 
331                                               AliHLTComponentTriggerData& trigData, AliHLTUInt8_t* outputPtr, 
332                                               AliHLTUInt32_t& size, 
333                                               vector<AliHLTComponentBlockData>& outputBlocks )
334 {
335   // see header file for class documentation
336   
337   //  == init iter (pointer to datablock)
338   const AliHLTComponentBlockData* iter = NULL;
339   unsigned long ndx;
340   
341   //  == OUTdatatype pointer
342   //    AliHLTTPCClusterData* outPtr;
343   
344   AliHLTUInt8_t* outBPtr;
345   UInt_t offset, mysize, tSize = 0;
346   
347   outBPtr = outputPtr;
348   //    outPtr = (AliHLTTPCClusterData*)outBPtr;
349   
350   
351   for ( ndx = 0; ndx < evtData.fBlockCnt; ndx++ )
352     {
353       iter = blocks+ndx;
354       mysize = 0;
355       offset = tSize;
356       
357       if(fCompressionSwitch) // show selected mode
358         {
359           HLTDebug("Event 0x%08LX (%Lu) received datatype: %s - required datatype: %s",evtData.fEventID, evtData.fEventID, 
360                    DataType2Text(iter->fDataType).c_str(), DataType2Text(kAliHLTDataTypeDDLRaw).c_str());
361
362           // check if current block has correct data format
363           // if not, take next block
364           if ( iter->fDataType != (kAliHLTDataTypeDDLRaw|fOrigin.Data()) ) continue;
365         }
366       else
367         {
368           HLTDebug("Event 0x%08LX (%Lu) received datatype: %s - required datatype: %s",evtData.fEventID, evtData.fEventID,
369                    DataType2Text(iter->fDataType).c_str(), DataType2Text(AliHLTCompDefinitions::fgkDDLEncodedHuffmanAltroDataType).c_str());
370
371           // check if current block has correct data format
372           // if not, take next block
373           if ( iter->fDataType != (AliHLTCompDefinitions::fgkDDLEncodedHuffmanAltroDataType|fOrigin.Data()) ) continue;
374         }
375
376       // HLTDebug("HLT::HuffmanCompressor::DoEvent", "Event received", "Starting to process data");
377
378       fHuffmanCompressor->SetInputData(iter->fPtr, iter->fSize);
379
380       // validation test
381       // HLTDebug("input data pointer (HEX) = %x ", iter->fPtr);
382       // HLTDebug("input data size (bytes) = %i ", iter->fSize);
383       
384       fHuffmanCompressor->SetOutputData(outBPtr, size);
385       
386       // validation test
387       // HLTDebug("output data pointer (HEX) = %x ", outBPtr);
388       // HLTDebug("reserved output data size (bytes) = %i ", size);
389       
390       fHuffmanCompressor->ProcessData();
391       
392       //        outPtr = (AliHLTTPCClusterData*)outBPtr;
393       
394       mysize = fHuffmanCompressor->GetOutputDataSize();
395       
396       if(mysize != 0)
397         {
398           AliHLTComponentBlockData bd;
399           FillBlockData( bd );
400           bd.fOffset = offset;
401           bd.fSize = mysize;
402           bd.fSpecification = iter->fSpecification;
403           //AliHLTSubEventDescriptor::FillBlockAttributes( bd.fAttributes );
404           outputBlocks.push_back( bd );
405             
406           tSize += mysize;
407             outBPtr += mysize;
408             //outPtr = (AliHLTTPCClusterData*)outBPtr;
409             
410             if ( tSize > size )
411               {
412                 HLTFatal("HLT::TPCHuffmanCompressor::DoEvent: Too much data, data written over allowed buffer. Amount written: %lu, allowed amount: %lu.",tSize, size );
413                 return EMSGSIZE;
414               }
415             
416         } // end of output-block-generation
417       
418     }
419   
420   size = tSize;
421
422   return 0;   
423 }
424