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