]> git.uio.no Git - u/mrichter/AliRoot.git/blob - TPC/AliTPCCompression.cxx
Log replaced by Id
[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 #ifndef __DECCXX 
306   fTable.open(filename,ios::binary);
307 #else
308   fTable.open(filename);
309 #endif
310   Int_t dimTable=Table->Size();
311   //Table dimension is written into a file
312   fTable.write((char*)(&dimTable),sizeof(Int_t));
313   //One table is written into a file
314   for(Int_t i=0;i<dimTable;i++){
315     UChar_t CodeLen=Table->CodeLen()[i];
316     Double_t Code=Table->Code()[i];
317     fTable.write((char*)(&CodeLen),sizeof(UChar_t));
318     fTable.write((char*)(&Code),sizeof(Double_t));
319   } //end for
320   fTable.close();
321   delete Table;
322   return 0;
323 }
324 ////////////////////////////////////////////////////////////////////////////////////////
325 Int_t AliTPCCompression::CreateTables(const char* fSource,const Int_t NumTables){
326   //Tables manager
327   /*
328     Table index:
329     0==> Bunch length values     
330     1==> Time Bin values 
331     2==> 1-samples bunch
332     3==> Central samples
333     4==> Border samples
334   */
335   Int_t n=10;// 10 bits per symbol 
336   AliTPCHTable ** table = new AliTPCHTable*[NumTables];
337   //The table is inizialized with the rigth number of rows 
338   for(Int_t i=0;i<NumTables;i++){
339     table[i]=new  AliTPCHTable((Int_t)(TMath::Power(2,n)));
340     table[i]->SetVerbose(fVerbose);
341   }
342   //The frequencies are calculated and the tables are filled
343   if (fVerbose)
344     cout<<"Filling tables...\n";
345   //The get the frequencies 
346   FillTables(fSource,table,NumTables);
347
348   //This part will be used in the table optimization phase
349   /*
350   for(Int_t i=0;i<NumTables;i++){
351     table[i]->CompleteTable(i);
352   }
353   */
354   if(fVerbose){
355     cout<<"Entropy of Bunch length table........."<<table[0]->GetEntropy()<<endl;
356     cout<<"Entropy of Time bin table............."<<table[1]->GetEntropy()<<endl;
357     cout<<"Entropy of one Sample bunch table....."<<table[2]->GetEntropy()<<endl;
358     cout<<"Entropy of Central Sample table......."<<table[3]->GetEntropy()<<endl;
359     cout<<"Entropy Border Samples table.........."<<table[4]->GetEntropy()<<endl;
360   }
361   fStat.open("Statistics",ios::app);
362   fStat<<endl;
363   fStat<<"----------------- ENTROPY for castomized tables --------------------------"<<endl;
364   fStat<<"Entropy of Bunch length table......."<<table[0]->GetEntropy()<<endl;
365   fStat<<"Entropy of Time bin table..........."<<table[1]->GetEntropy()<<endl;
366   fStat<<"Entropy of one Sample bunch table..."<<table[2]->GetEntropy()<<endl;
367   fStat<<"Entropy of Central Sample table....."<<table[3]->GetEntropy()<<endl;
368   fStat<<"Entropy Border Samples table........"<<table[4]->GetEntropy()<<endl;
369   fStat.close();
370  
371   if (fVerbose)
372     cout<<"Tables filled \n";
373   
374   //Frequencies normalization
375   table[0]->NormalizeFrequencies();
376   table[1]->NormalizeFrequencies();
377   table[2]->NormalizeFrequencies();
378   table[3]->NormalizeFrequencies();
379   table[4]->NormalizeFrequencies();
380   
381   //Tables are saved in a sequence of text file and using the macro Histo.C is it possible to get
382   //a series of histograms rappresenting the frequency distribution
383   table[0]->StoreFrequencies("BunchLenFreq.txt");
384   table[1]->StoreFrequencies("TimeFreq.txt");
385   table[2]->StoreFrequencies("Sample1Freq.txt");
386   table[3]->StoreFrequencies("SCentralFreq.txt");
387   table[4]->StoreFrequencies("SBorderFreq.txt");
388   if (fVerbose)
389     cout<<"Creating Tables..\n";
390   //One Huffman tree is created for each table starting from the frequencies of the symbols
391   for(Int_t i=0;i<NumTables;i++){
392     table[i]->BuildHTable();
393     if (fVerbose==2){
394       cout<<"Number of elements inside the table:"<<table[i]->GetWordsNumber();
395       switch(i){
396       case 0:{
397         cout<<" (Bunch Length)"<<endl;
398         break;
399       }
400       case 1:{
401         cout<<" (Time Bin)"<<endl;
402         break;
403       }
404       case 2:{
405         cout<<" (1 Samples Bunch)"<<endl;
406         break;
407       }
408       case 3:{
409         cout<<" (Central Samples)"<<endl;
410         break;
411       }
412       case 4:{
413         cout<<" (Border Samples)"<<endl;
414         break;
415       }
416       }//end switch
417       table[i]->PrintTable();
418     }
419   }
420   //The tables are saved ad binary files
421   StoreTables(table,NumTables);
422   //The tables stored in memory are deleted; 
423   for(Int_t i=0;i<NumTables;i++)delete table[i];
424   delete [] table;
425   return 0;
426 }
427 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
428 Int_t AliTPCCompression::RetrieveTables(AliTPCHTable* table[],Int_t NumTable){
429   //This method retrieve the Huffman tables from a sequence of binary files
430   if (fVerbose)
431     cout<<"Retrieving tables from files \n";
432   //  ULong_t code;
433   Double_t code;
434   UChar_t codeLen;
435   ifstream fTable;  
436   char filename[15];
437   //The following for loop is used to generate the Huffman trees acording to the tables
438   for(Int_t k=0;k<NumTable;k++){
439     Int_t dim;//this variable contains the table dimension
440     sprintf(filename,"Table%d.dat",k); 
441 #ifndef __DECCXX 
442     fTable.open(filename,ios::binary);
443 #else
444     fTable.open(filename);
445 #endif
446     if(!fTable){cout<<"File doesn't exist:"<<filename<<endl; exit(1);}
447     fTable.read((char*)(&dim),sizeof(Int_t));
448     if (fVerbose)
449       cout<<"Table dimension: "<<dim<<endl;
450     table[k]=new AliTPCHTable(dim);
451     for(Int_t i=0;i<dim;i++){
452       fTable.read((char*)(&codeLen),sizeof(UChar_t));
453       table[k]->SetCodeLen(codeLen,i);
454       //      fTable.read((char*)(&code),sizeof(ULong_t));
455       fTable.read((char*)(&code),sizeof(Double_t));
456       table[k]->SetCode(Mirror((ULong_t)code,codeLen),i);
457     }//end for 
458     fTable.close();
459   }//end for 
460   if (fVerbose)
461     cout<<"Trees generated \n";
462   //At this point the trees are been built
463   return 0;
464 }
465
466 Int_t AliTPCCompression::CreateTablesFromTxtFiles(Int_t NumTable){
467   //This method creates a set of binary tables, needed by the Huffman
468   //algorith, starting from a set of frequencies tables stored in form of
469   //txt files
470   if (fVerbose)
471     cout<<"Retrieving frequencies from txt files \n";
472   ifstream fTable;  
473   char filename[15];
474   //Tables are read from the files (Each codeword has been "Mirrored")
475   AliTPCHTable **table = new AliTPCHTable*[NumTable];
476   for(Int_t k=0;k<NumTable;k++){
477     sprintf(filename,"Table%d.txt",k); 
478     cout<<filename<<endl;
479     fTable.open(filename);
480     if(!fTable){cout<<"File doesn't exist: "<<filename<<endl; exit(1);}
481     Int_t symbol=0;
482     Double_t freq=0;
483     table[k]=new AliTPCHTable(1024);
484     while(!fTable.eof()){
485       fTable>>freq;
486       if (fTable.good()){
487         if (freq<0){
488           cout<<"Frequency cannot be negative !!!\n";
489           exit(1);
490         }
491         table[k]->SetValFrequency(symbol,freq);
492       }
493       symbol++;
494     }//end while
495     fTable.clear();
496     fTable.close();
497   }//end for
498   fStat.open("Statistics",ios::app);
499   fStat<<endl;
500   fStat<<"----------------- ENTROPY for external txt tables --------------------------"<<endl;
501   fStat<<"Entropy of Bunch length table......."<<table[0]->GetEntropy()<<endl;
502   fStat<<"Entropy of Time bin table..........."<<table[1]->GetEntropy()<<endl;
503   fStat<<"Entropy of one Sample bunch table..."<<table[2]->GetEntropy()<<endl;
504   fStat<<"Entropy of Central Sample table....."<<table[3]->GetEntropy()<<endl;
505   fStat<<"Entropy Border Samples table........"<<table[4]->GetEntropy()<<endl;
506   fStat.close();
507   for(Int_t k=0;k<NumTable;k++){
508     table[k]->BuildHTable();
509   }//end for
510   //The tables are saved ad binary files
511   StoreTables(table,NumTable);  
512   //The tables stored in memory are deleted; 
513   for(Int_t i=0;i<NumTable;i++)delete table[i];
514   delete [] table;
515   return 0;
516 }
517
518 ////////////////////////////////////////////////////////////////////////////////////////
519 /*                               COMPRESSION                                          */
520 ////////////////////////////////////////////////////////////////////////////////////////
521
522 void AliTPCCompression::StoreValue(ULong_t val,UChar_t len){
523   //This method stores the value "val" of "len" bits into the internal buffer "fBuffer"
524   if (len<=fFreeBitsBuffer){           // val is not splitted in two buffer
525     fFreeBitsBuffer-=len;
526     fBuffer=fBuffer<<len;
527     fBuffer=fBuffer|val;    
528     if(!fFreeBitsBuffer){              // if the buffer is full it is written into a file 
529       f.write((char*)(&fBuffer),sizeof(ULong_t));       
530       fFreeBitsBuffer=fDimBuffer;
531       fBuffer=0;
532     }
533   }//end if
534   else{                               //val has to be splitted in two buffers
535     fBuffer=fBuffer<<fFreeBitsBuffer;
536     ULong_t temp;
537     temp=val;
538     temp=temp>>(len-fFreeBitsBuffer);
539     fBuffer=fBuffer|temp;
540     f.write((char*)(&fBuffer),sizeof(ULong_t));
541     fFreeBitsBuffer=fDimBuffer-(len-fFreeBitsBuffer);
542     val=val<<fFreeBitsBuffer;
543     val=val>>fFreeBitsBuffer;
544     fBuffer=val;
545   }//end else
546   return;
547 }
548 //////////////////////////////////////////////////////////////////////////////////////////////////
549 void AliTPCCompression::Flush(){
550   //The last buffer cannot be completely full so to save it 
551   //into the output file it is first necessary to fill it with an hexadecimal pattern
552   if(fFreeBitsBuffer<fDimBuffer){
553     fBuffer=fBuffer<<fFreeBitsBuffer;
554     f.write((char*)(&fBuffer),sizeof(ULong_t));  
555   }//end if
556   return;
557 }
558 //////////////////////////////////////////////////////////////////////////////////////////////////
559 ULong_t AliTPCCompression::Mirror(ULong_t val,UChar_t len)const{
560   //This method inverts the digits of the number "val" and length "len"
561   //indicates the number of digits of the number considered in binary notation
562   ULong_t specular=0;
563   ULong_t mask=0x1;
564   ULong_t bit;
565   for(Int_t i=0;i<len;i++){
566     bit=val&mask;
567     bit=bit>>i;
568     specular=specular<<1;
569     specular=specular|bit;
570     mask=mask<<1;
571   }
572   return specular;
573 }
574 //////////////////////////////////////////////////////////////////////////////////////////////////
575 Int_t AliTPCCompression::CompressData(AliTPCHTable* table[],Int_t NumTable,const char* fSource,const char* fDest){
576   //This method is used to compress the data stored in the Altro format file using specific tables
577   //calculated considering the frequencies of the symbol of the file that has to be compressed
578   cout<<" COMPRESSION "<<endl;
579   cout<<"compression of the file "<<fSource<<" Output File: "<<fDest<<endl;
580   //the output file is open
581 #ifndef __DECCXX 
582   f.open(fDest,ios::binary|ios::out);
583 #else
584   f.open(fDest,ios::out);
585 #endif
586   //Tables are written into the output file
587   for(Int_t k=0;k<NumTable;k++){
588     Int_t dim=table[k]->Size();
589     //Table dimension is written into a file
590     f.write((char*)(&dim),sizeof(Int_t));
591     //One table is written into a file
592     for(Int_t i=0;i<dim;i++){
593       UChar_t codeLen=table[k]->CodeLen()[i];
594       ULong_t code=(ULong_t)table[k]->Code()[i];
595       f.write((char*)(&codeLen),sizeof(UChar_t));
596       f.write((char*)(&code),sizeof(ULong_t));
597     } //end for
598   }//end for
599
600   // Source file is open
601   AliTPCBuffer160 buff(fSource,0);
602   //coded words are written into the output file
603   Int_t numWords,padNum,rowNum,secNum=0;
604   ULong_t storedWords=0;
605   Int_t value=0;
606   ULong_t numPackets=0;
607   while(buff.ReadTrailerBackward(numWords,padNum,rowNum,secNum) !=-1 ){
608     numPackets++;
609     if (numWords%4){
610       for(Int_t j=0;j<(4-numWords%4);j++){
611         value=buff.GetNextBackWord();
612       }//end for
613     }//end if
614
615     Int_t packet[1024];
616     Int_t timePos[345];
617     Int_t tp=0;
618     for(Int_t i=0;i<345;i++)timePos[i]=0;
619     for(Int_t i=0;i<1024;i++)packet[i]=0;
620
621     Int_t nextTableType=0;
622     Int_t bunchLen=0;
623     Int_t count=0;
624     for(Int_t i=0;i<numWords;i++){
625       value=buff.GetNextBackWord();
626       packet[i]=value;
627       if(nextTableType==1){
628         timePos[tp]=i;
629         tp++;
630       }
631       NextTable(value,nextTableType,bunchLen,count);
632     }//end for
633     //computing the Time gap between two bunches
634     Int_t temp=0;
635     tp--;
636     Int_t previousTime=packet[timePos[tp]];
637     for(Int_t i=tp-1;i>=0;i--){
638       Int_t timPos=timePos[i];
639       Int_t bunchLen=packet[timPos-1]-2;
640       temp=packet[timPos];
641       packet[timPos]=packet[timPos]-previousTime-bunchLen;
642       previousTime=temp;
643     }//end for
644     nextTableType=0;
645     count=0;
646     bunchLen=0;
647     Int_t timeBin=0;
648     //All the words for one pad are compressed and stored in the compress file
649     for(Int_t i=0;i<numWords;i++){
650       value=packet[i];
651       if(nextTableType==1)timeBin=value;
652       if(nextTableType>1){
653         //      ULong_t val=(ULong_t)table[nextTableType]->Code()[value];     // val is the code
654         Double_t val=table[nextTableType]->Code()[value];     // val is the code
655         UChar_t len=table[nextTableType]->CodeLen()[value];  // len is the length (number of bits)of val
656         StoreValue(Mirror((ULong_t)val,len),len);
657         storedWords++;
658       }//end if
659       NextTable(value,nextTableType,bunchLen,count);
660       if(nextTableType==0){
661         //      ULong_t val=(ULong_t)table[1]->Code()[timeBin];     // val is the code
662         Double_t val=table[1]->Code()[timeBin];     // val is the code
663         UChar_t len=table[1]->CodeLen()[timeBin];  // len is the length (number of bits)of val
664         StoreValue(Mirror((ULong_t)val,len),len);
665         //val=(ULong_t)table[nextTableType]->Code()[(bunchLen+2)];     // val is the code
666         val=table[nextTableType]->Code()[(bunchLen+2)];     // val is the code
667         len=table[nextTableType]->CodeLen()[(bunchLen+2)];  // len is the length (number of bits)of val
668         StoreValue(Mirror((ULong_t)val,len),len);
669         storedWords+=2;
670       }
671     }//end for
672     //Trailer
673     StoreValue(numWords,10);
674     StoreValue(padNum,10);
675     StoreValue(rowNum,10);
676     StoreValue(secNum,9);
677     StoreValue(1,1);
678     storedWords+=4;
679   }//end  while
680   StoreValue(numPackets,32);
681   cout<<"Number of strored packet: "<<numPackets<<endl;
682   StoreValue(1,1);
683   //The last buffen cannot be completely full
684   Flush();
685   cout<<"Number of stored words: "<<storedWords<<endl;
686   f.close();
687   return 0;
688 }
689
690 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
691 Int_t AliTPCCompression::CompressDataOptTables(Int_t NumTable,const char* fSource,const char* fDest){
692   //This method compress an Altro format file using a general set of tables stored as binary files to be provided
693   if (fVerbose){
694     cout<<" BackWord COMPRESSION "<<endl;
695     cout<<"compression of the file "<<fSource<<" Output File: "<<fDest<<endl;
696   }
697   //Tables are read from the files (Each codeword has been "Mirrored")
698   AliTPCHTable **table = new AliTPCHTable*[NumTable];
699   RetrieveTables(table,NumTable);
700   //the output file is open
701 #ifndef __DECCXX 
702   f.open(fDest,ios::binary|ios::out);
703 #else
704   f.open(fDest,ios::out);
705 #endif
706   // Source file is open
707   AliTPCBuffer160 buff(fSource,0);
708   //coded words are written into a file
709   Int_t numWords,padNum,rowNum,secNum=0;
710   ULong_t  storedWords=0;
711   Int_t    value=0;
712   ULong_t  numPackets=0;
713   Double_t stat[5]={0.,0.,0.,0.,0.};
714   ULong_t  trailerNumbers=0;
715   Double_t numElem[5]={0,0,0,0,0};
716   Double_t fillWords=0.;
717   fStat.open("Statistics",ios::app);
718   fStat<<endl;
719   fStat<<"-------------------COMPRESSION STATISTICS----------"<<endl;
720   Int_t end=1;
721   while(buff.ReadTrailerBackward(numWords,padNum,rowNum,secNum) !=-1 ){
722     if(end){
723       fillWords=buff.GetFillWordsNum();
724       end=0;
725     }//endif
726
727     numPackets++;
728     if (numWords%4){
729       fillWords+=4-numWords%4;
730       for(Int_t j=0;j<(4-numWords%4);j++){
731         value=buff.GetNextBackWord();
732       }//end for
733     }//end if
734
735     Int_t packet[1024];
736     Int_t timePos[345];
737     Int_t tp=0;
738     for(Int_t i=0;i<345;i++)timePos[i]=0;
739     for(Int_t i=0;i<1024;i++)packet[i]=0;
740
741     Int_t nextTableType=0;
742     Int_t bunchLen=0;
743     Int_t count=0;
744     for(Int_t i=0;i<numWords;i++){
745       value=buff.GetNextBackWord();
746       packet[i]=value;
747       if(nextTableType==1){
748         timePos[tp]=i;
749         tp++;
750       }
751       NextTable(value,nextTableType,bunchLen,count);
752     }//end for
753     //computing the Time gap between two bunches
754     Int_t temp=0;
755     tp--;
756     Int_t previousTime=packet[timePos[tp]];
757     for(Int_t i=tp-1;i>=0;i--){
758       Int_t timPos=timePos[i];
759       Int_t bunchLen=packet[timPos-1]-2;
760       temp=packet[timPos];
761       packet[timPos]=packet[timPos]-previousTime-bunchLen;
762       previousTime=temp;
763     }//end for
764
765     nextTableType=0;
766     count=0;
767     bunchLen=0;
768     Int_t timeBin=0;
769     for(Int_t i=0;i<numWords;i++){
770       value=packet[i];
771       if(nextTableType==1)timeBin=value;
772       if(nextTableType>1){
773         //ULong_t val=(ULong_t)table[nextTableType]->Code()[value];     // val is the code
774         Double_t val=table[nextTableType]->Code()[value];     // val is the code
775         UChar_t len=table[nextTableType]->CodeLen()[value];  // len is the length (number of bits)of val
776         stat[nextTableType]+=len;
777         numElem[nextTableType]++;
778         StoreValue((ULong_t)val,len);
779         storedWords++;
780       }//end if
781       NextTable(value,nextTableType,bunchLen,count);
782       if(nextTableType==0){
783         //      ULong_t val=(ULong_t)table[1]->Code()[timeBin];     // val is the code
784         Double_t val=table[1]->Code()[timeBin];     // val is the code
785         UChar_t len=table[1]->CodeLen()[timeBin];  // len is the length (number of bits)of val
786         stat[1]+=len;
787         numElem[1]++;
788         StoreValue((ULong_t)val,len);
789         //      val=(ULong_t)table[nextTableType]->Code()[(bunchLen+2)];     // val is the code
790         val=table[nextTableType]->Code()[(bunchLen+2)];     // val is the code
791         len=table[nextTableType]->CodeLen()[(bunchLen+2)];  // len is the length (number of bits)of val
792         StoreValue((ULong_t)val,len);
793         stat[nextTableType]+=len;
794         numElem[nextTableType]++;
795         storedWords+=2;
796       }
797     }//end for
798     //Trailer
799     StoreValue(numWords,10);
800     StoreValue(padNum,10);
801     StoreValue(rowNum,10);
802     StoreValue(secNum,9);
803     StoreValue(1,1);
804     storedWords+=4;
805     trailerNumbers++;
806   }//end  while
807   StoreValue(numPackets,32);
808   if(fVerbose)
809     cout<<"Number of strored packets: "<<numPackets<<endl;
810   StoreValue(1,1);
811   //The last buffen cannot be completely full
812   Flush();
813   if(fVerbose)
814     cout<<"Number of stored words: "<<storedWords<<endl;
815   f.close();
816   //Tables are deleted
817   for(Int_t i=0;i<NumTable;i++){
818     delete table[i];
819   }//end for
820   delete [] table;
821   Double_t dimension=(ULong_t)TMath::Ceil((stat[0]+stat[1]+stat[2]+stat[3]+stat[4])/8)+trailerNumbers*5;
822   fStat<<"Trailer Dimension in bytes......"<<trailerNumbers*5<<endl;
823   fStat<<"Data Dimension in bytes........."<<(ULong_t)TMath::Ceil((stat[0]+stat[1]+stat[2]+stat[3]+stat[4])/8)<<endl;
824   fStat<<"Compressed file dimension......."<<(ULong_t)dimension<<endl;
825   /*
826   fStat<<(ULong_t)trailerNumbers<<endl;
827   fStat<<(ULong_t)fillWords<<endl;
828   fStat<<(ULong_t)numElem[0]<<endl;
829   fStat<<(ULong_t)numElem[1]<<endl;
830   fStat<<(ULong_t)numElem[2]<<endl;
831   fStat<<(ULong_t)numElem[3]<<endl;
832   fStat<<(ULong_t)numElem[4]<<endl;
833   */
834   fillWords=(fillWords+numElem[0]+numElem[1]+numElem[2]+numElem[3]+numElem[4]+trailerNumbers*4)*10/8;
835   fStat<<"Original file dimension........."<<(ULong_t)fillWords<<endl;
836
837   Double_t ratio=(dimension/fillWords)*100;
838   fStat<<"Compression ratio (Compressed/Uncompressed)..."<<ratio<<"%"<<endl;
839   fStat<<endl;
840   if (numElem[0])
841     fStat<<"Bunch length size in bytes......"<<(ULong_t)TMath::Ceil(stat[0]/8)<<" Comppression.."<<(stat[0]/numElem[0])*10<<"%"<<endl;
842   if (numElem[1])  
843     fStat<<"Time gap size in bytes.........."<<(ULong_t)TMath::Ceil(stat[1]/8)<<" Comppression.."<<(stat[1]/numElem[1])*10<<"%"<<endl;
844   if (numElem[2]+numElem[3]+numElem[4])  
845     fStat<<"Amplitude values in bytes......."<<(ULong_t)TMath::Ceil((stat[2]+stat[3]+stat[4])/8)<<" Comppression.."<<
846       ((stat[2]+stat[3]+stat[4])/(numElem[2]+numElem[3]+numElem[4]))*10<<"%"<<endl;
847   if (numElem[2])
848   fStat<<"     One Samples in bytes............"<<(ULong_t)TMath::Ceil(stat[2]/8)<<" Comppression.."<<(stat[2]/numElem[2])*10<<"%"<<endl;
849   if (numElem[3])
850   fStat<<"     Central Samples size in bytes..."<<(ULong_t)TMath::Ceil(stat[3]/8)<<" Comppression.."<<(stat[3]/numElem[3])*10<<"%"<<endl;
851   if (numElem[4])
852   fStat<<"     Border Samples size in bytes...."<<(ULong_t)TMath::Ceil(stat[4]/8)<<" Comppression.."<<(stat[4]/numElem[4])*10<<"%"<<endl;
853   fStat<<endl;
854   fStat<<"Average number of bits per word"<<endl;
855   if (numElem[0])
856     fStat<<"Bunch length ......"<<stat[0]/numElem[0]<<endl;
857   if (numElem[1])
858     fStat<<"Time gap .........."<<stat[1]/numElem[1]<<endl;
859   if (numElem[2])
860     fStat<<"One Samples........"<<stat[2]/numElem[2]<<endl;
861   if (numElem[3])
862     fStat<<"Central Samples ..."<<stat[3]/numElem[3]<<endl;
863   if (numElem[4])
864     fStat<<"Border Samples....."<<stat[4]/numElem[4]<<endl;
865   fStat.close();
866   return 0;
867 }
868
869 ////////////////////////////////////////////////////////////////////////////////////////
870
871 ////////////////////////////////////////////////////////////////////////////////////////
872 /*                               DECOMPRESSION                                        */
873 ////////////////////////////////////////////////////////////////////////////////////////
874 void AliTPCCompression::CreateTrees(AliTPCHNode *RootNode[],const Int_t NumTables){
875   //The first part of the compressed file cotains the tables
876   //The following for loop is used to generate the Huffman trees acording to the tables
877   if(fVerbose)
878     cout<<"Creating the Huffman trees \n";
879   AliTPCHNode *node=0;
880   //  ULong_t code;
881   Double_t code;
882   UChar_t codeLen;
883   //loop over the numbero of tables
884   for(Int_t k=0;k<NumTables;k++){
885     RootNode[k]=new AliTPCHNode(); //RootNode is the root of the tree
886     Int_t dim;//this variable contains the table dimension
887     f.read((char*)(&dim),sizeof(Int_t));
888     if (fVerbose)
889       cout<<"Table dimension: "<<dim<<endl;
890     //loop over the words of a table
891     for(Int_t i=0;i<dim;i++){
892       f.read((char*)(&codeLen),sizeof(UChar_t));
893       //f.read((char*)(&code),sizeof(ULong_t));
894       f.read((char*)(&code),sizeof(Double_t));
895       node=RootNode[k];
896       for(Int_t j=1;j<=codeLen;j++){
897         ULong_t bit,val=0;
898         val=(ULong_t)TMath::Power(2,codeLen-j);
899         bit=(ULong_t)code&val; 
900         AliTPCHNode *temp=node;
901         if(bit){
902           node=node->GetRight();
903           if(!node){
904             node=new AliTPCHNode();
905             temp->SetRight(node);
906           }//end if
907         }//end if
908         else{
909           node=node->GetLeft();
910           if(!node){
911             node=new AliTPCHNode();
912             temp->SetLeft(node);
913           }//end if
914         }//end else
915       }//end for
916       if(codeLen){
917         node->SetSymbol(i);
918         node->SetFrequency(codeLen);
919       }//end if
920       //cout<<node->GetSymbol()<<"  "<<(Int_t)node->GetFrequency()<<endl;
921     }//end for 
922   }//end for 
923   if (fVerbose)
924     cout<<"Trees generated \n";
925   //At this point the trees are been built
926 }
927 //////////////////////////////////////////////////////////////////////////////////////////////////
928 void AliTPCCompression::CreateTreesFromFile(AliTPCHNode *RootNode[],const Int_t NumTables){
929   //For each table this method builds the associate Huffman tree starting from the codeword and 
930   //the codelength of each symbol 
931   if(fVerbose)
932     cout<<"Creating the Huffman trees \n";
933   AliTPCHNode *node=0;
934   // ULong_t code;
935   Double_t code;
936   UChar_t codeLen;
937   ifstream fTable;  
938   char filename[15];
939   //The following for loop is used to generate the Huffman trees acording to the tables
940   //loop over the tables
941   for(Int_t k=0;k<NumTables;k++){
942     RootNode[k]=new AliTPCHNode(); //RootNode is the root of the tree
943     Int_t dim=0;//this variable contains the table dimension
944     sprintf(filename,"Table%d.dat",k); 
945 #ifndef __DECCXX 
946     fTable.open(filename,ios::binary);
947 #else
948     fTable.open(filename);
949 #endif
950     fTable.read((char*)(&dim),sizeof(Int_t));
951     if (fVerbose)
952       cout<<"Table dimension: "<<dim<<endl;
953     //loop over the words of one table
954     for(Int_t i=0;i<dim;i++){
955       fTable.read((char*)(&codeLen),sizeof(UChar_t));
956       //fTable.read((char*)(&code),sizeof(ULong_t));
957       fTable.read((char*)(&code),sizeof(Double_t));
958       node=RootNode[k];
959       for(Int_t j=1;j<=codeLen;j++){
960         ULong_t bit,val=0;
961         val=(ULong_t)TMath::Power(2,codeLen-j);
962         bit=(ULong_t)code&val; 
963         AliTPCHNode *temp=node;
964         if(bit){
965           node=node->GetRight();
966           if(!node){
967             node=new AliTPCHNode();
968             temp->SetRight(node);
969           }//end if 
970         }//end if
971         else{
972           node=node->GetLeft();
973           if(!node){
974             node=new AliTPCHNode();
975             temp->SetLeft(node);
976           }//end if
977         }//end else
978       }//end for
979       if(codeLen){
980         node->SetSymbol(i);
981         node->SetFrequency(codeLen);
982       }//end if
983     }//end for 
984     fTable.close();
985   }//end for 
986   if (fVerbose)
987     cout<<"Trees generated \n";
988   //At this point the trees are been built
989 }
990 //////////////////////////////////////////////////////////////////////////////////////////////////
991 void AliTPCCompression::DeleteHuffmanTree(AliTPCHNode* node){
992   //This function deletes all the nodes of an Huffman tree
993   //In an Huffman tree any internal node has always two children 
994   if (node){
995     DeleteHuffmanTree(node->GetLeft());
996     DeleteHuffmanTree(node->GetRight());
997     //    cout<<node->GetSymbol()<<"  "<<(Int_t)node->GetFrequency()<<endl;
998     delete node;
999   }
1000 }
1001 //////////////////////////////////////////////////////////////////////////////////////////////////
1002 void AliTPCCompression::VisitHuffmanTree(AliTPCHNode* node){
1003   //This function realizes an in order visit of a binary tree 
1004   if (node){
1005     cout<<node->GetSymbol()<<" "<<node->GetFrequency()<<endl;
1006     VisitHuffmanTree(node->GetLeft());
1007     VisitHuffmanTree(node->GetRight());
1008   }
1009 }
1010 //////////////////////////////////////////////////////////////////////////////////////////////////
1011 ULong_t AliTPCCompression::ReadWord(Int_t NumberOfBit){
1012   //This method retrieves a word of a specific number of bits from the file through the internal buffer 
1013   ULong_t result=0;
1014   ULong_t bit=0;
1015   for (Int_t i=0;i<NumberOfBit;i++){
1016     if (fReadBits==32){
1017       fPos-=sizeof(ULong_t);
1018       f.seekg(fPos);
1019       f.read((char*)(&fBuffer),sizeof(ULong_t));
1020       fReadBits=0;
1021     }//end if
1022     ULong_t mask=0;
1023     mask=(ULong_t)TMath::Power(2,fReadBits);
1024     bit=fBuffer&mask;
1025     bit=bit>>fReadBits;
1026     fReadBits++;
1027     bit=bit<<i;
1028     result=result|bit;
1029   }//end for
1030   return result;
1031 }
1032 //////////////////////////////////////////////////////////////////////////////////////////////////
1033 void AliTPCCompression::ReadTrailer(Int_t &WordsNumber,Int_t &PadNumber,Int_t &RowNumber,Int_t &SecNumber){
1034   //It retrieves a trailer 
1035   ReadWord(1);
1036   SecNumber=ReadWord(9);
1037   RowNumber=ReadWord(10);
1038   PadNumber=ReadWord(10);
1039   WordsNumber=ReadWord(10);
1040   return;
1041 }
1042 //////////////////////////////////////////////////////////////////////////////////////////////////
1043 ULong_t AliTPCCompression::GetDecodedWord(AliTPCHNode* root){
1044   //This method retrieves a decoded word.
1045   AliTPCHNode *node=root;
1046   ULong_t symbol=0;
1047   Bool_t decoded=0;
1048   while(!decoded){
1049     ULong_t bit=ReadWord(1);
1050     if(bit)
1051       node=node->GetRight();
1052     else
1053       node=node->GetLeft();
1054     if (!(node->GetLeft())){
1055       symbol=node->GetSymbol();
1056       decoded=1;
1057     }
1058   }//end while
1059   return symbol;
1060 }
1061 //////////////////////////////////////////////////////////////////////////////////////////////////
1062 Int_t AliTPCCompression::DecompressData(Int_t NumTables,const char* fname,char* fDest){
1063   //Decompression method 
1064   cout<<"   DECOMPRESSION:"<<endl;
1065   cout<<"Source File "<<fname<<" Destination File "<<fDest<<endl;
1066 #ifndef __DECCXX 
1067   f.open(fname,ios::binary|ios::in);
1068 #else
1069   f.open(fname,ios::in);
1070 #endif
1071   if(!f){cout<<"File doesn't exist:"<<fname<<endl;;return -1;}
1072   AliTPCHNode ** rootNode = new AliTPCHNode*[NumTables];
1073   //Creation of the Huffman trees
1074   CreateTrees(rootNode,NumTables);
1075   //to go to the end of the file
1076   f.seekg(0,ios::end);
1077   //to get the file dimension in byte
1078   fPos=f.tellg();
1079   fPos-=sizeof(ULong_t);
1080   f.seekg(fPos);
1081   fReadBits=0;
1082   fBuffer=0;
1083   f.read((char*)(&fBuffer),sizeof(ULong_t));
1084   Int_t bit=0;
1085   ULong_t mask=0x1;
1086   while(!bit){
1087     bit=fBuffer&mask;
1088     mask=mask<<1;
1089     fReadBits++;
1090   }
1091   ULong_t packetNumber=ReadWord(sizeof(ULong_t)*8);
1092   cout<<"Number of Packect: "<<packetNumber<<endl;
1093   AliTPCBuffer160 bufferFile(fDest,1);
1094   ULong_t k=0;
1095   ULong_t wordsRead=0; //number of read coded words 
1096   while(k<packetNumber){
1097     Int_t numWords,padNumber,rowNumber,secNumber=0;
1098     ReadTrailer(numWords,padNumber,rowNumber,secNumber);
1099     k++;
1100     wordsRead+=4;
1101     Int_t previousTime=-1;
1102     Int_t time=0;
1103     Int_t nextTableType=0;
1104     Int_t bunchLen=0;
1105     Int_t count=0;
1106     for(Int_t i=0;i<numWords;i++){
1107       ULong_t symbol=GetDecodedWord(rootNode[nextTableType]);
1108       wordsRead++;
1109       //Time reconstruction
1110       if (nextTableType==1){
1111         if (previousTime!=-1){
1112           previousTime=symbol+previousTime+bunchLen;
1113         }
1114         else previousTime=symbol;
1115         time=previousTime;
1116       }
1117       if(nextTableType>1)
1118         bufferFile.FillBuffer(symbol);
1119       NextTable(symbol,nextTableType,bunchLen,count); 
1120       if(nextTableType==0){
1121         bufferFile.FillBuffer(time);
1122         bufferFile.FillBuffer(bunchLen+2);
1123         bunchLen=0;
1124       }
1125     }//end for
1126     bufferFile.WriteTrailer(numWords,padNumber,rowNumber,secNumber);
1127   }//end while
1128   cout<<"Number of decoded words:"<<wordsRead<<endl;
1129   f.close();
1130   //The trees are deleted 
1131   for(Int_t j=0;j<NumTables;j++){
1132       DeleteHuffmanTree(rootNode[j]);
1133   }//end for
1134   delete [] rootNode; 
1135   return 0; 
1136 }
1137
1138 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1139
1140 Int_t AliTPCCompression::DecompressDataOptTables(Int_t NumTables,const char* fname,char* fDest){
1141   //This method decompress a file using separate Huffman tables
1142   if(fVerbose){
1143     cout<<"   DECOMPRESSION:"<<endl;
1144     cout<<"Source File "<<fname<<" Destination File "<<fDest<<endl; 
1145   }
1146   AliTPCHNode ** rootNode = new AliTPCHNode*[NumTables];
1147   //Creation of the Huffman trees
1148   CreateTreesFromFile(rootNode,NumTables);
1149 #ifndef __DECCXX
1150   f.open(fname,ios::binary|ios::in);
1151 #else
1152   f.open(fname,ios::in);
1153 #endif
1154   if(!f){cout<<"File doesn't exist:"<<fname<<endl;;return -1;}
1155   //to go to the end of the file
1156   f.seekg(0,ios::end);
1157   //to get the file dimension in byte
1158   fPos=f.tellg();
1159   fPos-=sizeof(ULong_t);
1160   f.seekg(fPos);
1161   fReadBits=0;
1162   fBuffer=0;
1163   f.read((char*)(&fBuffer),sizeof(ULong_t));
1164   Int_t bit=0;
1165   ULong_t mask=0x1;
1166   while(!bit){
1167     bit=fBuffer&mask;
1168     mask=mask<<1;
1169     fReadBits++;
1170   }
1171   ULong_t packetNumber=ReadWord(sizeof(ULong_t)*8);
1172   if(fVerbose){
1173     cout<<"Number of Packect: "<<packetNumber<<endl;
1174   }
1175   AliTPCBuffer160 bufferFile(fDest,1);
1176   ULong_t k=0;
1177   ULong_t wordsRead=0; //number of read coded words 
1178   while(k<packetNumber){
1179     Int_t numWords,padNumber,rowNumber,secNumber=0;
1180     ReadTrailer(numWords,padNumber,rowNumber,secNumber);
1181     k++;
1182     wordsRead+=4;
1183     Int_t previousTime=-1;
1184     Int_t time=0;
1185     Int_t nextTableType=0;
1186     Int_t bunchLen=0;
1187     Int_t count=0;
1188     for(Int_t i=0;i<numWords;i++){
1189       ULong_t symbol=GetDecodedWord(rootNode[nextTableType]);
1190       wordsRead++;
1191       //Time reconstruction
1192       if (nextTableType==1){
1193         if (previousTime!=-1){
1194           previousTime=symbol+previousTime+bunchLen;
1195         }
1196         else previousTime=symbol;
1197         time=previousTime;
1198       }
1199       if(nextTableType>1)
1200         bufferFile.FillBuffer(symbol);
1201       NextTable(symbol,nextTableType,bunchLen,count); 
1202       if(nextTableType==0){
1203         bufferFile.FillBuffer(time);
1204         bufferFile.FillBuffer(bunchLen+2);
1205         bunchLen=0;
1206       }
1207     }//end for
1208     bufferFile.WriteTrailer(numWords,padNumber,rowNumber,secNumber);
1209   }//end while
1210   if(fVerbose){
1211     cout<<"Number of decoded words:"<<wordsRead<<endl;
1212   }
1213   f.close();
1214   //The trees are deleted 
1215   for(Int_t j=0;j<NumTables;j++){
1216       DeleteHuffmanTree(rootNode[j]);
1217   }//end for
1218   delete [] rootNode;
1219   return 0; 
1220 }
1221
1222 ///////////////////////////////////////////////////////////////////////////////////////////
1223
1224 void AliTPCCompression::ReadAltroFormat(char* fileOut,char* fileIn)const{
1225   //This method creates a text file containing the same information stored in 
1226   //an Altro file. The information in the text file is organized pad by pad and 
1227   //and for each pad it consists in a sequence of bunches (Bunch length +2,
1228   //Time bin of the last amplitude sample in the bunch, amplitude values)
1229   //It is used mainly for debugging
1230   ofstream ftxt(fileOut);
1231   AliTPCBuffer160 buff(fileIn,0);
1232   Int_t numWords,padNum,rowNum,secNum=0;
1233   Int_t value=0;
1234   if (fVerbose) cout<<"Creating a txt file from an Altro Format file"<<endl;
1235   while(buff.ReadTrailerBackward(numWords,padNum,rowNum,secNum) !=-1 ){
1236     ftxt<<"S:"<<secNum<<" R:"<<rowNum<<" P:"<<padNum<<" W:"<<numWords<<endl;
1237     if (numWords%4){
1238       for(Int_t j=0;j<(4-numWords%4);j++){
1239         value=buff.GetNextBackWord();
1240       }//end for
1241     }//end if
1242     for(Int_t i=0;i<numWords;i++){
1243       value=buff.GetNextBackWord();
1244       ftxt<<value<<endl;
1245     }//end for
1246   }//end while
1247   ftxt.close();
1248   return;
1249 }
1250
1251 //////////////////////////////////////////////////////////////////////////////////////////