Adding support for raw data events without subevent header
[u/mrichter/AliRoot.git] / RAW / AliTPCCompression.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-2003, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /* $Id$ */
17
18
19 // This class contains the implementation of the 
20 // compression and decompression algorithms 
21 // Compression is performed reading the Altro data block (called packet) backward.
22 // Similarly decompression is also done backward so that the final file is restored
23 // after the compression and decompression phase.
24
25 #include <stdlib.h>
26 #include <TObjArray.h>
27 #include <Riostream.h>
28 #include <TMath.h>
29 #include <TSystem.h>
30 #include "AliAltroBuffer.h"
31 #include "AliTPCHNode.h"
32 #include "AliTPCHTable.h"
33 #include "AliTPCCompression.h"
34
35 ClassImp(AliTPCCompression)
36
37 //////////////////////////////////////////////////////////////////////////////////////////////////
38 AliTPCCompression::AliTPCCompression(){
39   //Defaul constructor
40   fDimBuffer=sizeof(UInt_t)*8;
41   fFreeBitsBuffer=fDimBuffer;
42   fBitsToRead=32;
43   fPos=0;
44   fBuffer=0;
45   fVerbose=0;
46   fFillWords=0;
47   fPointBuffer=0;
48   return;
49 }
50 //////////////////////////////////////////////////////////////////////////////////////////////////
51 AliTPCCompression::AliTPCCompression(const AliTPCCompression &source)
52   :TObject(source){
53   //Constructor
54   this->fDimBuffer=source.fDimBuffer;
55   this->fFreeBitsBuffer=source.fFreeBitsBuffer;
56   this->fBitsToRead=source.fBitsToRead;
57   this->fPos=source.fPos;
58   this->fBuffer=source.fBuffer;
59   this->fVerbose=source.fVerbose;
60   this->fFillWords=source.fFillWords;
61   this->fPointBuffer=source.fPointBuffer;
62   return;
63 }
64 //////////////////////////////////////////////////////////////////////////////////////////////////
65 AliTPCCompression&  AliTPCCompression::operator=(const AliTPCCompression &source){
66   //Redefinition of the assignment operator
67   this->fDimBuffer=source.fDimBuffer;
68   this->fFreeBitsBuffer=source.fFreeBitsBuffer;
69   this->fBitsToRead=source.fBitsToRead;
70   this->fPos=source.fPos;
71   this->fBuffer=source.fBuffer;
72   this->fVerbose=source.fVerbose;
73   this->fFillWords=source.fFillWords;
74   this->fPointBuffer=source.fPointBuffer;
75   return *this;
76
77 //////////////////////////////////////////////////////////////////////////////////////////////////
78 void AliTPCCompression::NextTable(Int_t Val,Int_t &NextTableType,Int_t &BunchLen,Int_t &Count)const{
79   //Depending on the data type (5 types of data) a specific table is called
80   /*
81     Table index:
82     0==> Bunch length value     
83     1==> Time Bin value 
84     2==> 1-samples bunch
85     3==> Central samples
86     4==> Border samples
87   */  
88   switch (NextTableType){
89   case 0:{
90     BunchLen=Val-2;
91     NextTableType=1;
92     break;
93   }//end case 0
94   case 1:{
95     if (BunchLen==1)NextTableType=2;
96     else{
97       NextTableType=4;
98       Count=1;
99     }
100     break;
101   }//end case 1
102   case 2:{
103     NextTableType=0;
104     break;
105   }//end case 2
106   case 3:{
107     Count++;
108     if (Count==(BunchLen-1)){
109       NextTableType=4;
110     }
111     break;
112   }//end case 3
113   case 4:{
114     if (Count==1){
115       if (BunchLen>2)
116         NextTableType=3;
117       else
118         Count++;
119     }
120     else
121       NextTableType=0;
122     break;
123   }//end case 4
124   }//end switch
125   return;
126 }
127
128
129 /////////////////////////////////////////////////////////////////////////////////////////////////////
130
131 Int_t AliTPCCompression::FillTables(const char* fSource,AliTPCHTable* table[],Int_t /*NumTables*/){
132   //This method is used to compute the frequencies of the symbols in the source file
133   AliAltroBuffer buff(fSource,0);
134   UInt_t countWords=0;
135   UInt_t countTrailer=0;
136   Int_t numWords,padNum,rowNum,secNum=0;
137   Int_t value=0;
138   UInt_t stat[5]={0,0,0,0,0};
139   Int_t endFill=0;
140   Int_t end=1;
141   while(buff.ReadTrailerBackward(numWords,padNum,rowNum,secNum)){
142     if(end){
143       endFill=buff.GetFillWordsNum();
144       end=0;
145     }//endif
146     countTrailer++;
147     if (numWords%4){
148       fFillWords+=4-numWords%4;
149       for(Int_t j=0;j<(4-numWords%4);j++){
150         value=buff.GetNextBackWord();
151       }//end for
152     }//end if
153     
154     Int_t packet[1024];
155     Int_t timePos[345];
156     Int_t tp=0;
157     for(Int_t i=0;i<345;i++)timePos[i]=0;
158     for(Int_t i=0;i<1024;i++)packet[i]=0;
159     
160     Int_t nextTableType=0;
161     Int_t bunchLen=0;
162     Int_t count=0;
163     for(Int_t i=0;i<numWords;i++){
164       value=buff.GetNextBackWord();
165       packet[i]=value;
166       if(nextTableType==1){
167         timePos[tp]=i;
168         tp++;
169       }
170       NextTable(value,nextTableType,bunchLen,count);
171     }//end for
172     //computing the Time gap between two bunches
173     Int_t temp=0;
174     tp--;
175     Int_t previousTime=packet[timePos[tp]];
176     for(Int_t i=tp-1;i>=0;i--){
177       Int_t timPos=timePos[i];
178       Int_t bunchLen=packet[timPos-1]-2;
179       temp=packet[timPos];
180       packet[timPos]=packet[timPos]-previousTime-bunchLen;
181       previousTime=temp;
182     }
183     nextTableType=0;
184     count=0;
185     bunchLen=0;
186     for(Int_t i=0;i<numWords;i++){
187       value=packet[i];
188       table[nextTableType]->SetFrequency(value);
189       stat[nextTableType]++;
190       NextTable(value,nextTableType,bunchLen,count);
191       countWords++;
192     }//end for
193   }//end while
194   cout<<"Number of words:       "<<countWords<<endl;
195   cout<<"Number of trailers:    "<<countTrailer<<endl;
196   cout<<"Number of fill words   "<<fFillWords+endFill<<endl;
197   cout<<"Total number of words: "<<countWords+countTrailer*4+fFillWords<<endl;
198   //STATISTICS  
199   fStat.open("Statistics");
200   fStat<<"Number of words:..........................................."<<countWords<<endl;
201   fStat<<"Number of trailers (4 10 bits words in each one)..........."<<countTrailer<<endl;
202   fStat<<"Number of fill words:......................................"<<fFillWords+endFill<<endl;
203   fStat<<"Total number of words:....................................."<<countWords+countTrailer*4+fFillWords+endFill<<endl;
204   fStat<<"-----------------------------------------"<<endl;
205   fStat<<"Number of Bunches............."<<stat[0]<<endl;
206   fStat<<"Number of Time bin............"<<stat[1]<<endl;
207   fStat<<"Number of One Samples Bunch..."<<stat[2]<<endl;
208   fStat<<"Number of Central Samples....."<<stat[3]<<endl;
209   fStat<<"Number of Border Samples......"<<stat[4]<<endl;
210   fStat<<"-----------------------------------------"<<endl;
211   UInt_t fileDimension=(UInt_t)TMath::Ceil(double((countTrailer*4+countWords+fFillWords+endFill)*10/8));
212   fStat<<"Total file Size in bytes.."<<fileDimension<<endl;
213   Double_t percentage=TMath::Ceil((fFillWords+endFill)*125)/fileDimension;
214   fStat<<"Fill Words................"<<(UInt_t)TMath::Ceil((fFillWords+endFill)*10/8)<<" bytes   "<<percentage<<"%"<<endl;  
215   percentage=(Double_t)countTrailer*500/fileDimension;
216   fStat<<"Trailer..................."<<countTrailer*5<<" bytes   "<<percentage<<"%"<<endl;
217
218   percentage=(Double_t)((stat[0]+stat[1]+stat[2]+stat[3]+stat[4])) *125/fileDimension;
219   fStat<<"Data......................"<<(UInt_t)TMath::Ceil((stat[0]+stat[1]+stat[2]+stat[3]+stat[4])*10/8)<<" bytes   "<<percentage<<"%"<<endl;
220
221   percentage=(Double_t)(stat[0]*125)/fileDimension;
222   fStat<<"Bunch....................."<<(UInt_t)TMath::Ceil(stat[0]*10/8)<<" bytes  "<<percentage<<"%"<<endl;  //  
223   percentage=(Double_t)(stat[1]*125)/fileDimension;
224   fStat<<"Time......................"<<(UInt_t)TMath::Ceil(stat[1]*10/8)<<" bytes  "<<percentage<<"%"<<endl;  //  
225
226
227   percentage=(Double_t)((stat[2]+stat[3]+stat[4])) *125/fileDimension;
228   fStat<<"Amplitude values.........."<<(UInt_t)TMath::Ceil((stat[2]+stat[3]+stat[4])*10/8)<<" bytes  "<<percentage<<"%"<<endl;
229   percentage=(Double_t)(stat[2]*125)/fileDimension;
230   fStat<<"     One Samples..............."<<(UInt_t)TMath::Ceil(stat[2]*10/8)<<" bytes  "<<percentage<<"%"<<endl;  //  
231   percentage=(Double_t)(stat[3]*125)/fileDimension;
232   fStat<<"     Central Samples..........."<<(UInt_t)TMath::Ceil(stat[3]*10/8)<<" bytes  "<<percentage<<"%"<<endl;  //  
233   percentage=(Double_t)(stat[4]*125)/fileDimension;
234   fStat<<"     Border Samples............"<<(UInt_t)TMath::Ceil(stat[4]*10/8)<<" bytes  "<<percentage<<"%"<<endl;  //  
235   fStat.close();
236   return 0;
237 }
238 ////////////////////////////////////////////////////////////////////////////////////////
239 Int_t AliTPCCompression::StoreTables(AliTPCHTable* table[],const Int_t NumTable){
240   //This method stores the tables in a sequence of binary file
241   char filename[15];
242   ofstream fTable;
243   for(Int_t k=0;k<NumTable;k++){
244     sprintf(filename,"Table%d.dat",k);
245 #ifndef __DECCXX 
246     fTable.open(filename,ios::binary);
247 #else
248     fTable.open(filename);
249 #endif
250     Int_t dim=table[k]->Size();
251     //Table dimension is written into a file
252     fTable.write((char*)(&dim),sizeof(Int_t));
253     //One table is written into a file
254     for(Int_t i=0;i<dim;i++){
255       UChar_t codeLen=table[k]->CodeLen()[i];
256       //      UInt_t code=(UInt_t)table[k]->Code()[i];
257       Double_t code=table[k]->Code()[i];
258       fTable.write((char*)(&codeLen),sizeof(UChar_t));
259       //fTable.write((char*)(&code),sizeof(UInt_t));
260       fTable.write((char*)(&code),sizeof(Double_t));
261     } //end for
262     fTable.close();
263   }//end for
264   return 0;
265 }
266 ////////////////////////////////////////////////////////////////////////////////////////
267 Int_t AliTPCCompression::CreateTableFormula(Double_t beta,UInt_t M,Int_t dim,Int_t Type){
268   // Type = 0 for Bunch length
269   // Type = 1 for Time Gap
270   UInt_t freq;
271   Double_t sum=0;
272   Double_t min=10;
273   Double_t alpha=0;
274   Double_t a=0;
275   AliTPCHTable *table=new AliTPCHTable(dim);
276   
277   freq=1;
278   Double_t freqArray[1024];
279   for(Int_t i=0;i<1024;i++){
280     freqArray[i]=0;
281   }
282   alpha=M*0.000000602+0.0104;
283   if (fVerbose)
284     cout<<"alpha "<<alpha<<endl;
285   for(Int_t x=0;x<dim;x++){
286     if (Type==1)
287       freqArray[x]=TMath::Power((x+1),-beta)*TMath::Exp(-alpha*(x+1));
288     else
289       freqArray[x]=TMath::Power((x+1),-beta);
290     sum+=freqArray[x];
291     if (freqArray[x]<min)min=freqArray[x];
292   }//end for
293   if (fVerbose)
294     cout<<"Minimun Value "<<min<<endl;
295   a=1/sum;
296   if (fVerbose)
297     cout<<"a Value: "<<a<<endl;
298   for(Int_t x=0;x<dim;x++){
299     if (Type==0)//Bunch length
300       if (x>=3)//minimum bunch length
301         table->SetValFrequency(x,a*freqArray[x]*1000);
302       else
303         table->SetValFrequency(x,0);
304     else //Time table
305       table->SetValFrequency(x,a*freqArray[x]);
306   }
307   table->BuildHTable();
308   ofstream fTable;
309   char filename[15];
310   sprintf(filename,"Table%d.dat",Type); 
311 #ifndef __DECCXX 
312   fTable.open(filename,ios::binary);
313 #else
314   fTable.open(filename);
315 #endif
316   Int_t dimTable=table->Size();
317   //Table dimension is written into a file
318   fTable.write((char*)(&dimTable),sizeof(Int_t));
319   //One table is written into a file
320   for(Int_t i=0;i<dimTable;i++){
321     UChar_t codeLen=table->CodeLen()[i];
322     Double_t code=table->Code()[i];
323     fTable.write((char*)(&codeLen),sizeof(UChar_t));
324     fTable.write((char*)(&code),sizeof(Double_t));
325   } //end for
326   fTable.close();
327   delete table;
328   return 0;
329 }
330 ////////////////////////////////////////////////////////////////////////////////////////
331 Int_t AliTPCCompression::CreateTables(const char* fSource,Int_t NumTables){
332   //Tables manager
333   /*
334     Table index:
335     0==> Bunch length values     
336     1==> Time Bin values 
337     2==> 1-samples bunch
338     3==> Central samples
339     4==> Border samples
340   */
341   Int_t n=10;// 10 bits per symbol 
342   AliTPCHTable ** table = new AliTPCHTable*[NumTables];
343   //The table is inizialized with the rigth number of rows 
344   for(Int_t i=0;i<NumTables;i++){
345     table[i]=new  AliTPCHTable((Int_t)(TMath::Power(2,n)));
346     table[i]->SetVerbose(fVerbose);
347   }
348   //The frequencies are calculated and the tables are filled
349   if (fVerbose)
350     cout<<"Filling tables...\n";
351   //The get the frequencies 
352   FillTables(fSource,table,NumTables);
353
354   //This part will be used in the table optimization phase
355   
356   for(Int_t i=0;i<NumTables;i++){
357     table[i]->CompleteTable(i);
358   }
359   
360   if(fVerbose){
361     cout<<"Entropy of Bunch length table........."<<table[0]->GetEntropy()<<endl;
362     cout<<"Entropy of Time bin table............."<<table[1]->GetEntropy()<<endl;
363     cout<<"Entropy of one Sample bunch table....."<<table[2]->GetEntropy()<<endl;
364     cout<<"Entropy of Central Sample table......."<<table[3]->GetEntropy()<<endl;
365     cout<<"Entropy Border Samples table.........."<<table[4]->GetEntropy()<<endl;
366   }
367   fStat.open("Statistics",ios::app);
368   fStat<<endl;
369   fStat<<"----------------- ENTROPY for castomized tables --------------------------"<<endl;
370   fStat<<"Entropy of Bunch length table......."<<table[0]->GetEntropy()<<endl;
371   fStat<<"Entropy of Time bin table..........."<<table[1]->GetEntropy()<<endl;
372   fStat<<"Entropy of one Sample bunch table..."<<table[2]->GetEntropy()<<endl;
373   fStat<<"Entropy of Central Sample table....."<<table[3]->GetEntropy()<<endl;
374   fStat<<"Entropy Border Samples table........"<<table[4]->GetEntropy()<<endl;
375   fStat.close();
376  
377   if (fVerbose)
378     cout<<"Tables filled \n";
379   
380   //Frequencies normalization
381   table[0]->NormalizeFrequencies();
382   table[1]->NormalizeFrequencies();
383   table[2]->NormalizeFrequencies();
384   table[3]->NormalizeFrequencies();
385   table[4]->NormalizeFrequencies();
386   
387   //Tables are saved in a sequence of text file and using the macro Histo.C is it possible to get
388   //a series of histograms rappresenting the frequency distribution
389   table[0]->StoreFrequencies("BunchLenFreq.txt");
390   table[1]->StoreFrequencies("TimeFreq.txt");
391   table[2]->StoreFrequencies("Sample1Freq.txt");
392   table[3]->StoreFrequencies("SCentralFreq.txt");
393   table[4]->StoreFrequencies("SBorderFreq.txt");
394   if (fVerbose)
395     cout<<"Creating Tables..\n";
396   //One Huffman tree is created for each table starting from the frequencies of the symbols
397   for(Int_t i=0;i<NumTables;i++){
398     table[i]->BuildHTable();
399     if (fVerbose==2){
400       cout<<"Number of elements inside the table:"<<table[i]->GetWordsNumber();
401       switch(i){
402       case 0:{
403         cout<<" (Bunch Length)"<<endl;
404         break;
405       }
406       case 1:{
407         cout<<" (Time Bin)"<<endl;
408         break;
409       }
410       case 2:{
411         cout<<" (1 Samples Bunch)"<<endl;
412         break;
413       }
414       case 3:{
415         cout<<" (Central Samples)"<<endl;
416         break;
417       }
418       case 4:{
419         cout<<" (Border Samples)"<<endl;
420         break;
421       }
422       }//end switch
423       table[i]->PrintTable();
424     }
425   }
426   //The tables are saved ad binary files
427   StoreTables(table,NumTables);
428   //The tables stored in memory are deleted; 
429   for(Int_t i=0;i<NumTables;i++)delete table[i];
430   delete [] table;
431   return 0;
432 }
433 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
434 Int_t AliTPCCompression::RetrieveTables(AliTPCHTable* table[],Int_t NumTable){
435   //This method retrieve the Huffman tables from a sequence of binary files
436   if (fVerbose)
437     cout<<"Retrieving tables from files \n";
438   //  UInt_t code;
439   Double_t code;
440   UChar_t codeLen;
441   ifstream fTable;  
442   char filename[256];
443   //The following for loop is used to generate the Huffman trees acording to the tables
444   for(Int_t k=0;k<NumTable;k++){
445     Int_t dim;//this variable contains the table dimension
446     sprintf(filename,"Table%d.dat",k); 
447 #ifndef __DECCXX 
448     fTable.open(filename,ios::binary);
449 #else
450     fTable.open(filename);
451 #endif
452     if(!fTable && gSystem->Getenv("ALICE_ROOT")){
453       fTable.clear();
454       sprintf(filename,"%s/RAW/Table%d.dat",gSystem->Getenv("ALICE_ROOT"),k); 
455 #ifndef __DECCXX 
456       fTable.open(filename,ios::binary);
457 #else
458       fTable.open(filename);
459 #endif
460     }
461     if(!fTable){
462       Error("RetrieveTables", "File doesn't exist: %s", filename);
463       return 1;
464     }
465     fTable.read((char*)(&dim),sizeof(Int_t));
466     if (fVerbose)
467       cout<<"Table dimension: "<<dim<<endl;
468     table[k]=new AliTPCHTable(dim);
469     for(Int_t i=0;i<dim;i++){
470       fTable.read((char*)(&codeLen),sizeof(UChar_t));
471       table[k]->SetCodeLen(codeLen,i);
472       //      fTable.read((char*)(&code),sizeof(UInt_t));
473       fTable.read((char*)(&code),sizeof(Double_t));
474       table[k]->SetCode(Mirror((UInt_t)code,codeLen),i);
475     }//end for 
476     fTable.close();
477   }//end for 
478   if (fVerbose)
479     cout<<"Trees generated \n";
480   //At this point the trees are been built
481   return 0;
482 }
483
484 Int_t AliTPCCompression::CreateTablesFromTxtFiles(Int_t NumTable){
485   //This method creates a set of binary tables, needed by the Huffman
486   //algorith, starting from a set of frequencies tables stored in form of
487   //txt files
488   if (fVerbose)
489     cout<<"Retrieving frequencies from txt files \n";
490   ifstream fTable;  
491   char filename[15];
492   //Tables are read from the files (Each codeword has been "Mirrored")
493   AliTPCHTable **table = new AliTPCHTable*[NumTable];
494   for(Int_t k=0;k<NumTable;k++){
495     sprintf(filename,"Table%d.txt",k); 
496     cout<<filename<<endl;
497     fTable.open(filename);
498     if(!fTable){
499       Error("CreateTablesFromTxtFiles", "File doesn't exist: %s", filename);
500       return 1;
501     }
502     Int_t symbol=0;
503     Double_t freq=0;
504     table[k]=new AliTPCHTable(1024);
505     while(!fTable.eof()){
506       fTable>>freq;
507       if (fTable.good()){
508         if (freq<0){
509           cout<<"Frequency cannot be negative !!!\n";
510           exit(1);
511         }
512         table[k]->SetValFrequency(symbol,freq);
513       }
514       symbol++;
515     }//end while
516     fTable.clear();
517     fTable.close();
518   }//end for
519   fStat.open("Statistics",ios::app);
520   fStat<<endl;
521   fStat<<"----------------- ENTROPY for external txt tables --------------------------"<<endl;
522   fStat<<"Entropy of Bunch length table......."<<table[0]->GetEntropy()<<endl;
523   fStat<<"Entropy of Time bin table..........."<<table[1]->GetEntropy()<<endl;
524   fStat<<"Entropy of one Sample bunch table..."<<table[2]->GetEntropy()<<endl;
525   fStat<<"Entropy of Central Sample table....."<<table[3]->GetEntropy()<<endl;
526   fStat<<"Entropy Border Samples table........"<<table[4]->GetEntropy()<<endl;
527   fStat.close();
528   for(Int_t k=0;k<NumTable;k++){
529     table[k]->BuildHTable();
530   }//end for
531   //The tables are saved ad binary files
532   StoreTables(table,NumTable);  
533   //The tables stored in memory are deleted; 
534   for(Int_t i=0;i<NumTable;i++)delete table[i];
535   delete [] table;
536   return 0;
537 }
538
539 ////////////////////////////////////////////////////////////////////////////////////////
540 /*                               COMPRESSION                                          */
541 ////////////////////////////////////////////////////////////////////////////////////////
542
543 void AliTPCCompression::StoreValue(UInt_t val,UChar_t len){
544   //This method stores the value "val" of "len" bits into the internal buffer "fBuffer"
545   if (len<=fFreeBitsBuffer){           // val is not splitted in two buffer
546     fFreeBitsBuffer-=len;
547     fBuffer=fBuffer<<len;
548     fBuffer=fBuffer|val;    
549     if(!fFreeBitsBuffer){              // if the buffer is full it is written into a file 
550       f.write((char*)(&fBuffer),sizeof(UInt_t));        
551       fFreeBitsBuffer=fDimBuffer;
552       fBuffer=0;
553     }
554   }//end if
555   else{                               //val has to be splitted in two buffers
556     fBuffer=fBuffer<<fFreeBitsBuffer;
557     UInt_t temp;
558     temp=val;
559     temp=temp>>(len-fFreeBitsBuffer);
560     fBuffer=fBuffer|temp;
561     f.write((char*)(&fBuffer),sizeof(UInt_t));
562     fFreeBitsBuffer=fDimBuffer-(len-fFreeBitsBuffer);
563     val=val<<fFreeBitsBuffer;
564     val=val>>fFreeBitsBuffer;
565     fBuffer=val;
566   }//end else
567   return;
568 }
569 //////////////////////////////////////////////////////////////////////////////////////////////////
570 void AliTPCCompression::Flush(){
571   //The last buffer cannot be completely full so to save it 
572   //into the output file it is first necessary to fill it with an hexadecimal pattern
573   if(fFreeBitsBuffer<fDimBuffer){
574     fBuffer=fBuffer<<fFreeBitsBuffer;
575     f.write((char*)(&fBuffer),sizeof(UInt_t));   
576   }//end if
577   return;
578 }
579 //////////////////////////////////////////////////////////////////////////////////////////////////
580 UInt_t AliTPCCompression::Mirror(UInt_t val,UChar_t len)const{
581   //This method inverts the digits of the number "val" and length "len"
582   //indicates the number of digits of the number considered in binary notation
583   UInt_t specular=0;
584   UInt_t mask=0x1;
585   UInt_t bit;
586   for(Int_t i=0;i<len;i++){
587     bit=val&mask;
588     bit=bit>>i;
589     specular=specular<<1;
590     specular=specular|bit;
591     mask=mask<<1;
592   }
593   return specular;
594 }
595
596 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
597 Int_t AliTPCCompression::CompressDataOptTables(Int_t NumTable,const char* fSource,const char* fDest){
598   //This method compress an Altro format file using a general set of tables stored as binary files to be provided
599   if (fVerbose){
600     cout<<" BackWord COMPRESSION "<<endl;
601     cout<<"compression of the file "<<fSource<<" Output File: "<<fDest<<endl;
602   }
603   //Tables are read from the files (Each codeword has been "Mirrored")
604   AliTPCHTable **table = new AliTPCHTable*[NumTable];
605   for(Int_t i=0;i<NumTable;i++) table[i] = NULL;
606   if (RetrieveTables(table,NumTable) != 0) {
607     for(Int_t i=0;i<NumTable;i++) delete table[i];
608     delete [] table;
609     return 1;
610   }
611   //the output file is open
612   f.clear();
613 #ifndef __DECCXX 
614   f.open(fDest,ios::binary|ios::out);
615 #else
616   f.open(fDest,ios::out);
617 #endif
618   // Source file is open
619   AliAltroBuffer buff(fSource,0);
620   //coded words are written into a file
621   Int_t numWords,padNum,rowNum,secNum=0;
622   UInt_t  storedWords=0;
623   Int_t    value=0;
624   UInt_t  numPackets=0;
625   Double_t stat[5]={0.,0.,0.,0.,0.};
626   UInt_t  trailerNumbers=0;
627   Double_t numElem[5]={0,0,0,0,0};
628   Double_t fillWords=0.;
629   fStat.clear();
630   fStat.open("Statistics",ios::app);
631   fStat<<endl;
632   fStat<<"-------------------COMPRESSION STATISTICS----------"<<endl;
633   Int_t end=1;
634   while(buff.ReadTrailerBackward(numWords,padNum,rowNum,secNum)){
635     if(end){
636       fillWords=buff.GetFillWordsNum();
637       end=0;
638     }//endif
639
640     numPackets++;
641     if (numWords%4){
642       fillWords+=4-numWords%4;
643       for(Int_t j=0;j<(4-numWords%4);j++){
644         value=buff.GetNextBackWord();
645       }//end for
646     }//end if
647
648     Int_t packet[1024];
649     Int_t timePos[345];
650     Int_t tp=0;
651     for(Int_t i=0;i<345;i++)timePos[i]=0;
652     for(Int_t i=0;i<1024;i++)packet[i]=0;
653
654     Int_t nextTableType=0;
655     Int_t bunchLen=0;
656     Int_t count=0;
657     for(Int_t i=0;i<numWords;i++){
658       value=buff.GetNextBackWord();
659       packet[i]=value;
660       if(nextTableType==1){
661         timePos[tp]=i;
662         tp++;
663       }
664       NextTable(value,nextTableType,bunchLen,count);
665     }//end for
666     //computing the Time gap between two bunches
667     Int_t temp=0;
668     tp--;
669     Int_t previousTime=packet[timePos[tp]];
670     for(Int_t i=tp-1;i>=0;i--){
671       Int_t timPos=timePos[i];
672       Int_t bunchLen=packet[timPos-1]-2;
673       temp=packet[timPos];
674       packet[timPos]=packet[timPos]-previousTime-bunchLen;
675       previousTime=temp;
676     }//end for
677
678     nextTableType=0;
679     count=0;
680     bunchLen=0;
681     Int_t timeBin=0;
682     for(Int_t i=0;i<numWords;i++){
683       value=packet[i];
684       if(nextTableType==1)timeBin=value;
685       if(nextTableType>1){
686         //UInt_t val=(UInt_t)table[nextTableType]->Code()[value];     // val is the code
687         Double_t val=table[nextTableType]->Code()[value];     // val is the code
688         UChar_t len=table[nextTableType]->CodeLen()[value];  // len is the length (number of bits)of val
689         stat[nextTableType]+=len;
690         numElem[nextTableType]++;
691         StoreValue((UInt_t)val,len);
692         storedWords++;
693       }//end if
694       NextTable(value,nextTableType,bunchLen,count);
695       if(nextTableType==0){
696         //      UInt_t val=(UInt_t)table[1]->Code()[timeBin];     // val is the code
697         Double_t val=table[1]->Code()[timeBin];     // val is the code
698         UChar_t len=table[1]->CodeLen()[timeBin];  // len is the length (number of bits)of val
699         stat[1]+=len;
700         numElem[1]++;
701         StoreValue((UInt_t)val,len);
702         //      val=(UInt_t)table[nextTableType]->Code()[(bunchLen+2)];     // val is the code
703         val=table[nextTableType]->Code()[(bunchLen+2)];     // val is the code
704         len=table[nextTableType]->CodeLen()[(bunchLen+2)];  // len is the length (number of bits)of val
705         StoreValue((UInt_t)val,len);
706         stat[nextTableType]+=len;
707         numElem[nextTableType]++;
708         storedWords+=2;
709       }
710     }//end for
711     //Trailer
712     StoreValue(numWords,10);
713     StoreValue(padNum,10);
714     StoreValue(rowNum,10);
715     StoreValue(secNum,9);
716     StoreValue(1,1);
717     storedWords+=4;
718     trailerNumbers++;
719   }//end  while
720   StoreValue(numPackets,32);
721   if(fVerbose)
722     cout<<"Number of strored packets: "<<numPackets<<endl;
723   StoreValue(1,1);
724   //The last buffen cannot be completely full
725   Flush();
726   if(fVerbose)
727     cout<<"Number of stored words: "<<storedWords<<endl;
728   f.close();
729   //Tables are deleted
730   for(Int_t i=0;i<NumTable;i++){
731     delete table[i];
732   }//end for
733   delete [] table;
734   Double_t dimension=(UInt_t)TMath::Ceil((stat[0]+stat[1]+stat[2]+stat[3]+stat[4])/8)+trailerNumbers*5;
735   fStat<<"Trailer Dimension in bytes......"<<trailerNumbers*5<<endl;
736   fStat<<"Data Dimension in bytes........."<<(UInt_t)TMath::Ceil((stat[0]+stat[1]+stat[2]+stat[3]+stat[4])/8)<<endl;
737   fStat<<"Compressed file dimension......."<<(UInt_t)dimension<<endl;
738   /*
739   fStat<<(UInt_t)trailerNumbers<<endl;
740   fStat<<(UInt_t)fillWords<<endl;
741   fStat<<(UInt_t)numElem[0]<<endl;
742   fStat<<(UInt_t)numElem[1]<<endl;
743   fStat<<(UInt_t)numElem[2]<<endl;
744   fStat<<(UInt_t)numElem[3]<<endl;
745   fStat<<(UInt_t)numElem[4]<<endl;
746   */
747   fillWords=(fillWords+numElem[0]+numElem[1]+numElem[2]+numElem[3]+numElem[4]+trailerNumbers*4)*10/8;
748   fStat<<"Original file dimension........."<<(UInt_t)fillWords<<endl;
749
750   Double_t ratio=(dimension/fillWords)*100;
751   fStat<<"Compression ratio (Compressed/Uncompressed)..."<<ratio<<"%"<<endl;
752   fStat<<endl;
753   if (numElem[0])
754     fStat<<"Bunch length size in bytes......"<<(UInt_t)TMath::Ceil(stat[0]/8)<<" Comppression.."<<(stat[0]/numElem[0])*10<<"%"<<endl;
755   if (numElem[1])  
756     fStat<<"Time gap size in bytes.........."<<(UInt_t)TMath::Ceil(stat[1]/8)<<" Comppression.."<<(stat[1]/numElem[1])*10<<"%"<<endl;
757   if (numElem[2]+numElem[3]+numElem[4])  
758     fStat<<"Amplitude values in bytes......."<<(UInt_t)TMath::Ceil((stat[2]+stat[3]+stat[4])/8)<<" Comppression.."<<
759       ((stat[2]+stat[3]+stat[4])/(numElem[2]+numElem[3]+numElem[4]))*10<<"%"<<endl;
760   if (numElem[2])
761   fStat<<"     One Samples in bytes............"<<(UInt_t)TMath::Ceil(stat[2]/8)<<" Comppression.."<<(stat[2]/numElem[2])*10<<"%"<<endl;
762   if (numElem[3])
763   fStat<<"     Central Samples size in bytes..."<<(UInt_t)TMath::Ceil(stat[3]/8)<<" Comppression.."<<(stat[3]/numElem[3])*10<<"%"<<endl;
764   if (numElem[4])
765   fStat<<"     Border Samples size in bytes...."<<(UInt_t)TMath::Ceil(stat[4]/8)<<" Comppression.."<<(stat[4]/numElem[4])*10<<"%"<<endl;
766   fStat<<endl;
767   fStat<<"Average number of bits per word"<<endl;
768   if (numElem[0])
769     fStat<<"Bunch length ......"<<stat[0]/numElem[0]<<endl;
770   if (numElem[1])
771     fStat<<"Time gap .........."<<stat[1]/numElem[1]<<endl;
772   if (numElem[2])
773     fStat<<"One Samples........"<<stat[2]/numElem[2]<<endl;
774   if (numElem[3])
775     fStat<<"Central Samples ..."<<stat[3]/numElem[3]<<endl;
776   if (numElem[4])
777     fStat<<"Border Samples....."<<stat[4]/numElem[4]<<endl;
778   fStat.close();
779   return 0;
780 }
781
782 ////////////////////////////////////////////////////////////////////////////////////////
783
784 ////////////////////////////////////////////////////////////////////////////////////////
785 /*                               DECOMPRESSION                                        */
786 ////////////////////////////////////////////////////////////////////////////////////////
787
788 Int_t AliTPCCompression::CreateTreesFromFile(AliTPCHNode *RootNode[],Int_t NumTables){
789   //For each table this method builds the associate Huffman tree starting from the codeword and 
790   //the codelength of each symbol 
791   if(fVerbose)
792     cout<<"Creating the Huffman trees \n";
793   AliTPCHNode *node=0;
794   // UInt_t code;
795   Double_t code;
796   UChar_t codeLen;
797   ifstream fTable;  
798   char filename[256];
799   //The following for loop is used to generate the Huffman trees acording to the tables
800   //loop over the tables
801   for(Int_t k=0;k<NumTables;k++){
802     RootNode[k]=new AliTPCHNode(); //RootNode is the root of the tree
803     Int_t dim=0;//this variable contains the table dimension
804     sprintf(filename,"Table%d.dat",k); 
805 #ifndef __DECCXX 
806     fTable.open(filename,ios::binary);
807 #else
808     fTable.open(filename);
809 #endif
810     if(!fTable && gSystem->Getenv("ALICE_ROOT")){
811       fTable.clear();
812       sprintf(filename,"%s/RAW/Table%d.dat",gSystem->Getenv("ALICE_ROOT"),k); 
813 #ifndef __DECCXX 
814       fTable.open(filename,ios::binary);
815 #else
816       fTable.open(filename);
817 #endif
818     }
819     if(!fTable){
820       Error("CreateTreesFromFile", "File doesn't exist: %s", filename);
821       return 1;
822     }
823     fTable.read((char*)(&dim),sizeof(Int_t));
824     if (fVerbose)
825       cout<<"Table dimension: "<<dim<<endl;
826     //loop over the words of one table
827     for(Int_t i=0;i<dim;i++){
828       fTable.read((char*)(&codeLen),sizeof(UChar_t));
829       //fTable.read((char*)(&code),sizeof(UInt_t));
830       fTable.read((char*)(&code),sizeof(Double_t));
831       node=RootNode[k];
832       for(Int_t j=1;j<=codeLen;j++){
833         UInt_t bit,val=0;
834         //      val=(UInt_t)TMath::Power(2,codeLen-j);
835         val=(UInt_t)(1<<(codeLen-j));
836         bit=(UInt_t)code&val; 
837         AliTPCHNode *temp=node;
838         if(bit){
839           node=node->GetRight();
840           if(!node){
841             node=new AliTPCHNode();
842             temp->SetRight(node);
843           }//end if 
844         }//end if
845         else{
846           node=node->GetLeft();
847           if(!node){
848             node=new AliTPCHNode();
849             temp->SetLeft(node);
850           }//end if
851         }//end else
852       }//end for
853       if(codeLen){
854         node->SetSymbol(i);
855         node->SetFrequency(codeLen);
856       }//end if
857     }//end for 
858     fTable.close();
859   }//end for 
860   if (fVerbose)
861     cout<<"Trees generated \n";
862   //At this point the trees are been built
863   return 0;
864 }
865
866 Int_t AliTPCCompression::CreateLUTsFromTrees(AliTPCHNode *RootNode[],Int_t NumTables,UInt_t *LUTDimension[],AliTPCHNode **LUTNode[]){
867   //For each Huffman tree this method builds the associate look-up-table for fast 
868   //decoding of compressed data.
869   //Should be called after CreateTreesFromFile.
870   if(fVerbose)
871     cout<<"Creating the LUTs \n";
872   AliTPCHNode *node=0;
873
874   //loop over the tables
875   for(Int_t k=0;k<NumTables;k++){
876     UInt_t dim = 1<<fgkTableDimension;
877     LUTDimension[k] = new UInt_t[dim];
878     LUTNode[k] = new AliTPCHNode*[dim];
879     //loop over the words of one LUT
880     for(UInt_t i=0;i<dim;i++){
881       UInt_t buffer = i;
882       node=RootNode[k];
883       LUTDimension[k][i] = GetDecodedLUTBuffer(&node,&buffer);
884       LUTNode[k][i] = node;
885       //      cout<<"LUT "<<k<<" "<<i<<" "<<LUTDimension[k][i]<<" "<<LUTNode[k][i]<<" "<<LUTNode[k][i]->GetSymbol()<<endl;
886     }
887   }
888   if (fVerbose)
889     cout<<"LUTs generated \n";
890   //At this point the LUTs are built
891   return 0;
892 }
893 //////////////////////////////////////////////////////////////////////////////////////////////////
894 void AliTPCCompression::DeleteHuffmanTree(AliTPCHNode* node){
895   //This function deletes all the nodes of an Huffman tree
896   //In an Huffman tree any internal node has always two children 
897   if (node){
898     DeleteHuffmanTree(node->GetLeft());
899     DeleteHuffmanTree(node->GetRight());
900     //    cout<<node->GetSymbol()<<"  "<<(Int_t)node->GetFrequency()<<endl;
901     delete node;
902   }
903 }
904 //////////////////////////////////////////////////////////////////////////////////////////////////
905 void AliTPCCompression::VisitHuffmanTree(AliTPCHNode* node){
906   //This function realizes an in order visit of a binary tree 
907   if (node){
908     cout<<node->GetSymbol()<<" "<<node->GetFrequency()<<endl;
909     VisitHuffmanTree(node->GetLeft());
910     VisitHuffmanTree(node->GetRight());
911   }
912 }
913 //////////////////////////////////////////////////////////////////////////////////////////////////
914 UInt_t AliTPCCompression::ReadWord(UInt_t NumberOfBit){
915   //This method retrieves a word of a specific number of bits from the file through the internal buffer 
916   UInt_t result=0;
917   UInt_t bit=0;
918   for (UInt_t i=0;i<NumberOfBit;i++){
919     if (fBitsToRead==0){
920       fPos-=sizeof(UInt_t);
921       f.seekg(fPos);
922       f.read((char*)(&fBuffer),sizeof(UInt_t));
923       fBitsToRead=32;
924     }//end if
925     UInt_t mask=(UInt_t)(1<<(32-fBitsToRead));
926     bit=fBuffer&mask;
927     bit=bit>>(32-fBitsToRead);
928     fBitsToRead--;
929     bit=bit<<i;
930     result=result|bit;
931   }//end for
932   return result;
933 }
934 //////////////////////////////////////////////////////////////////////////////////////////////////
935 UInt_t AliTPCCompression::ReadWordBuffer(UInt_t NumberOfBit){
936   //This method retrieves a word of a specific number of bits from the file through the buffer 
937   UInt_t result=0;
938
939   if(NumberOfBit<=fBitsToRead) {
940     result = fBuffer&((1<<NumberOfBit)-1);
941     fBuffer=fBuffer>>NumberOfBit;
942     fBitsToRead-=NumberOfBit;
943   }
944   else {
945     fPointBuffer--;
946     UInt_t tempbuffer = *fPointBuffer;
947     if((NumberOfBit-fBitsToRead) != 32)
948       tempbuffer=tempbuffer&((1<<(NumberOfBit-fBitsToRead))-1);
949     tempbuffer=tempbuffer<<fBitsToRead;
950     result = fBuffer|tempbuffer;
951     fBuffer=*fPointBuffer;
952     fBitsToRead=(32+fBitsToRead)-NumberOfBit;
953     fBuffer=fBuffer>>(32-fBitsToRead);
954   }
955
956   return result;
957 }
958
959 //////////////////////////////////////////////////////////////////////////////////////////////////
960 inline void AliTPCCompression::AdjustWordBuffer(UInt_t NumberOfBit){
961   //This method retrieves a word of a specific number of bits from the file through the buffer
962   //The method is used together with LUTs for fast decoding
963   if(NumberOfBit<=fBitsToRead) {
964     fBuffer=fBuffer>>NumberOfBit;
965     fBitsToRead-=NumberOfBit;
966   }
967   else {
968     fPointBuffer--;
969     fBuffer=*fPointBuffer;
970     fBitsToRead=(32+fBitsToRead)-NumberOfBit;
971     fBuffer=fBuffer>>(32-fBitsToRead);
972   }
973 }
974
975 //////////////////////////////////////////////////////////////////////////////////////////////////
976 inline UInt_t AliTPCCompression::ReadWordBufferWithLUTs(){
977   //This method retrieves a word of a specific number of bits from the file through the buffer
978   //The method is used together with LUTs for fast decoding
979   if(fgkTableDimension<=fBitsToRead)
980     return fBuffer&((1<<fgkTableDimension)-1);
981   else {
982     UInt_t tempbuffer = *(fPointBuffer-1);
983     tempbuffer=tempbuffer&((1<<(fgkTableDimension-fBitsToRead))-1);
984     tempbuffer=tempbuffer<<fBitsToRead;
985     return fBuffer|tempbuffer;
986   }
987 }
988
989 //////////////////////////////////////////////////////////////////////////////////////////////////
990 inline UInt_t AliTPCCompression::ReadBitFromWordBuffer(){
991   //This method retrieves a bit from the file through the buffer 
992   UInt_t result=0;
993
994   if (fBitsToRead==0){
995     fPointBuffer--;
996     fBuffer=*fPointBuffer;
997     fBitsToRead=32;
998   }//end if
999   result=fBuffer&0x1;
1000   fBitsToRead--;
1001   fBuffer=fBuffer>>1;
1002   return result;
1003 }
1004
1005 //////////////////////////////////////////////////////////////////////////////////////////////////
1006 inline UInt_t AliTPCCompression::ReadBitFromLUTBuffer(UInt_t *buffer){
1007   //This method retrieves a word of a bit out of the LUT buffer
1008   UInt_t result=0;
1009
1010   result=*buffer&0x1;
1011   *buffer=*buffer>>1;
1012   return result;
1013 }
1014
1015 //////////////////////////////////////////////////////////////////////////////////////////////////
1016 void AliTPCCompression::ReadTrailer(Int_t &WordsNumber,Int_t &PadNumber,Int_t &RowNumber,Int_t &SecNumber,Bool_t Memory){
1017   //It retrieves a trailer 
1018   if(Memory){
1019     ReadBitFromWordBuffer();
1020     SecNumber=ReadWordBuffer(9);
1021     RowNumber=ReadWordBuffer(10);
1022     PadNumber=ReadWordBuffer(10);
1023     WordsNumber=ReadWordBuffer(10);
1024   }
1025   else{
1026     ReadWord(1);
1027     SecNumber=ReadWord(9);
1028     RowNumber=ReadWord(10);
1029     PadNumber=ReadWord(10);
1030     WordsNumber=ReadWord(10);
1031   }
1032   return;
1033 }
1034 //////////////////////////////////////////////////////////////////////////////////////////////////
1035 inline UInt_t AliTPCCompression::GetDecodedWordBuffer(AliTPCHNode* root){
1036   //This method retrieves a decoded word.
1037   AliTPCHNode *node=root;
1038   UInt_t symbol=0;
1039   Bool_t decoded=0;
1040
1041   while(!decoded){
1042     UInt_t bit=ReadBitFromWordBuffer();
1043     if(bit)
1044       node=node->GetRight();
1045     else
1046       node=node->GetLeft();
1047     if (!(node->GetLeft())){
1048       symbol=node->GetSymbol();
1049       decoded=1;
1050     }
1051   }//end while
1052   return symbol;
1053 }
1054
1055 //////////////////////////////////////////////////////////////////////////////////////////////////
1056 inline UInt_t AliTPCCompression::GetDecodedWordBufferWithLUTs(UInt_t* LUTDimension,AliTPCHNode** LUTNode){
1057   //This method retrieves a decoded word.
1058   UInt_t symbol=0;
1059   UInt_t buffer=0;
1060   Bool_t decoded=0;
1061
1062   buffer = ReadWordBufferWithLUTs();
1063   AliTPCHNode *node=LUTNode[buffer];
1064   if (!(node->GetLeft())){
1065     symbol=node->GetSymbol();
1066     decoded=1;
1067   }
1068   AdjustWordBuffer(LUTDimension[buffer]);
1069   while(!decoded){
1070     UInt_t bit=ReadBitFromWordBuffer();
1071     if(bit)
1072       node=node->GetRight();
1073     else
1074       node=node->GetLeft();
1075     if (!(node->GetLeft())){
1076       symbol=node->GetSymbol();
1077       decoded=1;
1078     }
1079   }//end while
1080   return symbol;
1081 }
1082
1083 //////////////////////////////////////////////////////////////////////////////////////////////////
1084 inline UInt_t AliTPCCompression::GetDecodedLUTBuffer(AliTPCHNode** node,UInt_t *buffer){
1085   //This method retrieves a decoded word for the LUTs.
1086   Bool_t decoded=0;
1087   UInt_t counter=0;
1088
1089   while(!decoded && counter<fgkTableDimension){
1090     UInt_t bit=ReadBitFromLUTBuffer(buffer);
1091     counter++;
1092     if(bit)
1093       *node=(*node)->GetRight();
1094     else
1095       *node=(*node)->GetLeft();
1096     if (!((*node)->GetLeft())){
1097       decoded=1;
1098     }
1099   }//end while
1100   return counter;
1101 }
1102
1103 inline UInt_t AliTPCCompression::GetDecodedWord(AliTPCHNode* root){
1104   //This method retrieves a decoded word.
1105   AliTPCHNode *node=root;
1106   UInt_t symbol=0;
1107   Bool_t decoded=0;
1108
1109   while(!decoded){
1110     UInt_t bit=ReadWord(1);
1111     if(bit)
1112       node=node->GetRight();
1113     else
1114       node=node->GetLeft();
1115     if (!(node->GetLeft())){
1116       symbol=node->GetSymbol();
1117       decoded=1;
1118     }
1119   }//end while
1120
1121   return symbol;
1122 }
1123 //////////////////////////////////////////////////////////////////////////////////////////////////
1124
1125 Int_t AliTPCCompression::DecompressDataOptTables(Int_t NumTables,const char* fname, const char* fDest){
1126   //This method decompress a file using separate Huffman tables
1127   if(fVerbose){
1128     cout<<"   DECOMPRESSION:"<<endl;
1129     cout<<"Source File "<<fname<<" Destination File "<<fDest<<endl; 
1130   }
1131   AliTPCHNode ** rootNode = new AliTPCHNode*[NumTables];
1132   for(Int_t i=0;i<NumTables;i++) rootNode[i] = NULL;
1133   //Creation of the Huffman trees
1134   if (CreateTreesFromFile(rootNode,NumTables) != 0) {
1135     for(Int_t i=0;i<NumTables;i++) {
1136       if (rootNode[i]) DeleteHuffmanTree(rootNode[i]);
1137     }
1138     delete [] rootNode;
1139     return 1;
1140   }
1141   f.clear();
1142 #ifndef __DECCXX
1143   f.open(fname,ios::binary|ios::in);
1144 #else
1145   f.open(fname,ios::in);
1146 #endif
1147   if(!f){
1148     Error("DecompressDataOptTables", "File doesn't exist:",fname);
1149     return -1;
1150   }
1151   //to go to the end of the file
1152   f.seekg(0,ios::end);
1153   //to get the file dimension in byte
1154   fPos=f.tellg();
1155   fPos-=sizeof(UInt_t);
1156   f.seekg(fPos);
1157   fBitsToRead=32;
1158   fBuffer=0;
1159   f.read((char*)(&fBuffer),sizeof(UInt_t));
1160   Int_t bit=0;
1161   UInt_t mask=0x1;
1162   while(!bit){
1163     bit=fBuffer&mask;
1164     mask=mask<<1;
1165     fBitsToRead--;
1166   }
1167   UInt_t packetNumber=ReadWord(sizeof(UInt_t)*8);
1168   if(fVerbose){
1169     cout<<"Number of Packect: "<<packetNumber<<endl;
1170   }
1171   AliAltroBuffer bufferFile(fDest,1);
1172   UInt_t k=0;
1173   UInt_t wordsRead=0; //number of read coded words 
1174   while(k<packetNumber){
1175     Int_t numWords,padNumber,rowNumber,secNumber=0;
1176     ReadTrailer(numWords,padNumber,rowNumber,secNumber,kFALSE);
1177     k++;
1178     wordsRead+=4;
1179     Int_t previousTime=-1;
1180     Int_t time=0;
1181     Int_t nextTableType=0;
1182     Int_t bunchLen=0;
1183     Int_t count=0;
1184     for(Int_t i=0;i<numWords;i++){
1185       UInt_t symbol=GetDecodedWord(rootNode[nextTableType]);
1186       wordsRead++;
1187       //Time reconstruction
1188       if (nextTableType==1){
1189         if (previousTime!=-1){
1190           previousTime=symbol+previousTime+bunchLen;
1191         }
1192         else previousTime=symbol;
1193         time=previousTime;
1194       }
1195       if(nextTableType>1)
1196         bufferFile.FillBuffer(symbol);
1197       NextTable(symbol,nextTableType,bunchLen,count); 
1198       if(nextTableType==0){
1199         bufferFile.FillBuffer(time);
1200         bufferFile.FillBuffer(bunchLen+2);
1201         bunchLen=0;
1202       }
1203     }//end for
1204     bufferFile.WriteTrailer(numWords,padNumber,rowNumber,secNumber);
1205   }//end while
1206   if(fVerbose){
1207     cout<<"Number of decoded words:"<<wordsRead<<endl;
1208   }
1209   f.close();
1210   //The trees are deleted 
1211   for(Int_t j=0;j<NumTables;j++){
1212       DeleteHuffmanTree(rootNode[j]);
1213   }//end for
1214   delete [] rootNode;
1215   return 0; 
1216 }
1217
1218 //////////////////////////////////////////////////////////////////////////////////////////////////
1219 Int_t AliTPCCompression::Decompress(AliTPCHNode *RootNode[],Int_t /*NumTables*/,char* PointBuffer,UInt_t BufferSize,UShort_t out[],UInt_t &dim){
1220   //This method decompress a file using separate Huffman tables
1221
1222   //  fPointBuffer=((UInt_t *)PointBuffer)+(UInt_t)(BufferSize/4)-1;
1223   fPointBuffer=(UInt_t *)(PointBuffer+BufferSize-4);
1224   fBitsToRead=32;
1225   fBuffer=0;
1226   
1227   fBuffer=*fPointBuffer;
1228   Int_t bit=0;
1229   while(!bit){
1230     bit=fBuffer&0x1;
1231     fBuffer=fBuffer>>1;
1232     fBitsToRead--;
1233   }//end while
1234   UInt_t packetNumber=ReadWordBuffer(sizeof(UInt_t)*8); //32 bits
1235   if (fVerbose){
1236     cout<<"First one has been found "<<endl;
1237     cout<<"Number of packets:"<<packetNumber<<endl;
1238   }//end if
1239   UInt_t k=0;
1240   UInt_t wordsRead=0; //number of read coded words
1241   while(k<packetNumber){
1242     Int_t numWords,padNumber,rowNumber,secNumber=0;
1243     ReadTrailer(numWords,padNumber,rowNumber,secNumber,kTRUE);
1244     out[dim]=numWords;
1245     dim++;
1246     out[dim]=padNumber;
1247     dim++;
1248     out[dim]=rowNumber;
1249     dim++;
1250     out[dim]=secNumber;
1251     dim++;
1252     //ftxt<<"S:"<<secNumber<<" R:"<<rowNumber<<" P:"<<padNumber<<" W:"<<numWords<<endl;
1253     //    padDigits->SetPadID(padNumber,rowNumber,secNumber,DDL);
1254     k++;
1255     wordsRead+=4;
1256     Int_t previousTime=-1;
1257     Int_t time=0;
1258     Int_t nextTableType=0;
1259     Int_t bunchLen=0;
1260     Int_t count=0;
1261     Int_t timeDigit=0;
1262     for(Int_t i=0;i<numWords;i++){
1263       UInt_t symbol=GetDecodedWordBuffer(RootNode[nextTableType]);
1264       wordsRead++;
1265       //Time reconstruction
1266       if (nextTableType==1){
1267         if (previousTime!=-1){
1268           previousTime=symbol+previousTime+bunchLen;
1269         }
1270         else previousTime=symbol;
1271         time=previousTime;
1272         out[dim]=bunchLen+2;
1273         dim++;
1274         out[dim]=time;
1275         dim++;
1276         timeDigit=time-bunchLen;
1277       }
1278       if(nextTableType>1){
1279         //
1280         //ftxt<<symbol<<endl;
1281         out[dim]=symbol;
1282         dim++;
1283         timeDigit++;
1284         //padDigits->SetDigits(symbol,timeDigit);
1285       }
1286       NextTable(symbol,nextTableType,bunchLen,count); 
1287       if(nextTableType==0){
1288         //
1289         //ftxt<<time<<endl;
1290         //  ftxt<<(bunchLen+2)<<endl;
1291         bunchLen=0;
1292       }
1293     }//end for
1294   }//end while
1295   return 0; 
1296 }
1297
1298 //////////////////////////////////////////////////////////////////////////////////////////////////
1299 Int_t AliTPCCompression::DecompressWithLUTs(AliTPCHNode *RootNode[],UInt_t *LUTDimension[],AliTPCHNode **LUTNode[],Int_t /*NumTables*/,char* PointBuffer,UInt_t BufferSize,UShort_t out[],UInt_t &dim){
1300   //This method decompress a file using separate Huffman tables and already prepared LUTs for fast decoding
1301
1302   //  fPointBuffer=((UInt_t *)PointBuffer)+(UInt_t)(BufferSize/4)-1;
1303   fPointBuffer=(UInt_t *)(PointBuffer+BufferSize-4);
1304   fBitsToRead=32;
1305   fBuffer=0;
1306   
1307   fBuffer=*fPointBuffer;
1308   Int_t bit=0;
1309   while(!bit){
1310     bit=fBuffer&0x1;
1311     fBuffer=fBuffer>>1;
1312     fBitsToRead--;
1313   }//end while
1314   UInt_t packetNumber=ReadWordBuffer(sizeof(UInt_t)*8); //32 bits
1315   if (fVerbose){
1316     cout<<"First one has been found "<<endl;
1317     cout<<"Number of packets:"<<packetNumber<<endl;
1318   }//end if
1319   UInt_t k=0;
1320   UInt_t wordsRead=0; //number of read coded words
1321   while(k<packetNumber){
1322     Int_t numWords,padNumber,rowNumber,secNumber=0;
1323     ReadTrailer(numWords,padNumber,rowNumber,secNumber,kTRUE);
1324     out[dim]=numWords;
1325     dim++;
1326     out[dim]=padNumber;
1327     dim++;
1328     out[dim]=rowNumber;
1329     dim++;
1330     out[dim]=secNumber;
1331     dim++;
1332     //ftxt<<"S:"<<secNumber<<" R:"<<rowNumber<<" P:"<<padNumber<<" W:"<<numWords<<endl;
1333     //    padDigits->SetPadID(padNumber,rowNumber,secNumber,DDL);
1334     k++;
1335     wordsRead+=4;
1336     Int_t previousTime=-1;
1337     Int_t time=0;
1338     Int_t nextTableType=0;
1339     Int_t bunchLen=0;
1340     Int_t count=0;
1341     Int_t timeDigit=0;
1342     for(Int_t i=0;i<numWords;i++){
1343       UInt_t symbol;
1344       if(i == (numWords-1))
1345         symbol = GetDecodedWordBuffer(RootNode[nextTableType]);
1346       else
1347         symbol=GetDecodedWordBufferWithLUTs(LUTDimension[nextTableType],LUTNode[nextTableType]);
1348       wordsRead++;
1349       //Time reconstruction
1350       if (nextTableType==1){
1351         if (previousTime!=-1){
1352           previousTime=symbol+previousTime+bunchLen;
1353         }
1354         else previousTime=symbol;
1355         time=previousTime;
1356         out[dim]=bunchLen+2;
1357         dim++;
1358         out[dim]=time;
1359         dim++;
1360         timeDigit=time-bunchLen;
1361       }
1362       if(nextTableType>1){
1363         //
1364         //ftxt<<symbol<<endl;
1365         out[dim]=symbol;
1366         dim++;
1367         timeDigit++;
1368         //padDigits->SetDigits(symbol,timeDigit);
1369       }
1370       NextTable(symbol,nextTableType,bunchLen,count); 
1371       if(nextTableType==0){
1372         //
1373         //ftxt<<time<<endl;
1374         //  ftxt<<(bunchLen+2)<<endl;
1375         bunchLen=0;
1376       }
1377     }//end for
1378   }//end while
1379   return 0; 
1380 }
1381
1382 //////////////////////////////////////////////////////////////////////////////////////////////////
1383 Int_t AliTPCCompression::DestroyTables(AliTPCHNode *RootNode[],Int_t NumTables){
1384   //The trees are deleted
1385   for(Int_t j=0;j<NumTables;j++){
1386     DeleteHuffmanTree(RootNode[j]);
1387   }//end for
1388   if(fVerbose)
1389     cout<<"Huffman trees destroyed"<<endl;
1390   return 0;
1391 }
1392 //////////////////////////////////////////////////////////////////////////////////////////////////
1393
1394 void AliTPCCompression::ReadAltroFormat(char* fileOut,char* fileIn)const{
1395   //This method creates a text file containing the same information stored in 
1396   //an Altro file. The information in the text file is organized pad by pad and 
1397   //and for each pad it consists in a sequence of bunches (Bunch length +2,
1398   //Time bin of the last amplitude sample in the bunch, amplitude values)
1399   //It is used mainly for debugging
1400   ofstream ftxt(fileOut);
1401   AliAltroBuffer buff(fileIn,0);
1402   Int_t numWords,padNum,rowNum,secNum=0;
1403   Int_t value=0;
1404   if (fVerbose) cout<<"Creating a txt file from an Altro Format file"<<endl;
1405   while(buff.ReadTrailerBackward(numWords,padNum,rowNum,secNum)){
1406     ftxt<<"S:"<<secNum<<" R:"<<rowNum<<" P:"<<padNum<<" W:"<<numWords<<endl;
1407     if (numWords%4){
1408       for(Int_t j=0;j<(4-numWords%4);j++){
1409         value=buff.GetNextBackWord();
1410       }//end for
1411     }//end if
1412     for(Int_t i=0;i<numWords;i++){
1413       value=buff.GetNextBackWord();
1414       ftxt<<value<<endl;
1415     }//end for
1416   }//end while
1417   ftxt.close();
1418   return;
1419 }
1420
1421 //////////////////////////////////////////////////////////////////////////////////////////