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