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