]> git.uio.no Git - u/mrichter/AliRoot.git/blame - RAW/AliTPCCompression.cxx
bugfix
[u/mrichter/AliRoot.git] / RAW / 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 **************************************************************************/
9f992f70 15
30c1018e 16/* $Id$ */
a79660fb 17
9f992f70 18
a79660fb 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
146d2dbf 25#include <stdlib.h>
2e9f335b 26#include <TObjArray.h>
b62e2a95 27#include <Riostream.h>
28#include <TMath.h>
1d98347a 29#include <TSystem.h>
3ea47630 30#include "AliAltroBuffer.h"
bea6b2a4 31#include "AliTPCHNode.h"
32#include "AliTPCHTable.h"
c9bd9d3d 33#include "AliTPCCompression.h"
2e9f335b 34
35ClassImp(AliTPCCompression)
36//////////////////////////////////////////////////////////////////////////////////////////////////
37AliTPCCompression::AliTPCCompression(){
a79660fb 38 //Defaul constructor
0b3c7dfc 39 fDimBuffer=sizeof(UInt_t)*8;
2e9f335b 40 fFreeBitsBuffer=fDimBuffer;
41 fReadBits=0;
42 fPos=0;
43 fBuffer=0;
44 fVerbose=0;
45 fFillWords=0;
c9bd9d3d 46 fPointBuffer=0;
2e9f335b 47 return;
48}
49//////////////////////////////////////////////////////////////////////////////////////////////////
b66321bb 50AliTPCCompression::AliTPCCompression(const AliTPCCompression &source)
51 :TObject(source){
a79660fb 52 //Constructor
2e9f335b 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;
c9bd9d3d 60 this->fPointBuffer=source.fPointBuffer;
2e9f335b 61 return;
62}
63//////////////////////////////////////////////////////////////////////////////////////////////////
64AliTPCCompression& AliTPCCompression::operator=(const AliTPCCompression &source){
a79660fb 65 //Redefinition of the assignment operator
2e9f335b 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;
c9bd9d3d 73 this->fPointBuffer=source.fPointBuffer;
2e9f335b 74 return *this;
75}
76//////////////////////////////////////////////////////////////////////////////////////////////////
a79660fb 77void 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
2e9f335b 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
2e9f335b 127
128/////////////////////////////////////////////////////////////////////////////////////////////////////
129
09f6432c 130Int_t AliTPCCompression::FillTables(const char* fSource,AliTPCHTable* table[],Int_t /*NumTables*/){
2e9f335b 131 //This method is used to compute the frequencies of the symbols in the source file
3ea47630 132 AliAltroBuffer buff(fSource,0);
0b3c7dfc 133 UInt_t countWords=0;
134 UInt_t countTrailer=0;
a79660fb 135 Int_t numWords,padNum,rowNum,secNum=0;
136 Int_t value=0;
0b3c7dfc 137 UInt_t stat[5]={0,0,0,0,0};
a79660fb 138 Int_t endFill=0;
139 Int_t end=1;
3ea47630 140 while(buff.ReadTrailerBackward(numWords,padNum,rowNum,secNum)){
a79660fb 141 if(end){
142 endFill=buff.GetFillWordsNum();
143 end=0;
2e9f335b 144 }//endif
a79660fb 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();
2e9f335b 150 }//end for
151 }//end if
152
a79660fb 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;
2e9f335b 158
a79660fb 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++;
2e9f335b 168 }
a79660fb 169 NextTable(value,nextTableType,bunchLen,count);
2e9f335b 170 }//end for
171 //computing the Time gap between two bunches
172 Int_t temp=0;
a79660fb 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;
2e9f335b 181 }
a79660fb 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++;
2e9f335b 191 }//end for
192 }//end while
a79660fb 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;
2e9f335b 197 //STATISTICS
a79660fb 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;
0b3c7dfc 210 UInt_t fileDimension=(UInt_t)TMath::Ceil(double((countTrailer*4+countWords+fFillWords+endFill)*10/8));
a79660fb 211 fStat<<"Total file Size in bytes.."<<fileDimension<<endl;
212 Double_t percentage=TMath::Ceil((fFillWords+endFill)*125)/fileDimension;
0b3c7dfc 213 fStat<<"Fill Words................"<<(UInt_t)TMath::Ceil((fFillWords+endFill)*10/8)<<" bytes "<<percentage<<"%"<<endl;
a79660fb 214 percentage=(Double_t)countTrailer*500/fileDimension;
215 fStat<<"Trailer..................."<<countTrailer*5<<" bytes "<<percentage<<"%"<<endl;
2e9f335b 216
a79660fb 217 percentage=(Double_t)((stat[0]+stat[1]+stat[2]+stat[3]+stat[4])) *125/fileDimension;
0b3c7dfc 218 fStat<<"Data......................"<<(UInt_t)TMath::Ceil((stat[0]+stat[1]+stat[2]+stat[3]+stat[4])*10/8)<<" bytes "<<percentage<<"%"<<endl;
2e9f335b 219
a79660fb 220 percentage=(Double_t)(stat[0]*125)/fileDimension;
0b3c7dfc 221 fStat<<"Bunch....................."<<(UInt_t)TMath::Ceil(stat[0]*10/8)<<" bytes "<<percentage<<"%"<<endl; //
a79660fb 222 percentage=(Double_t)(stat[1]*125)/fileDimension;
0b3c7dfc 223 fStat<<"Time......................"<<(UInt_t)TMath::Ceil(stat[1]*10/8)<<" bytes "<<percentage<<"%"<<endl; //
2e9f335b 224
225
a79660fb 226 percentage=(Double_t)((stat[2]+stat[3]+stat[4])) *125/fileDimension;
0b3c7dfc 227 fStat<<"Amplitude values.........."<<(UInt_t)TMath::Ceil((stat[2]+stat[3]+stat[4])*10/8)<<" bytes "<<percentage<<"%"<<endl;
a79660fb 228 percentage=(Double_t)(stat[2]*125)/fileDimension;
0b3c7dfc 229 fStat<<" One Samples..............."<<(UInt_t)TMath::Ceil(stat[2]*10/8)<<" bytes "<<percentage<<"%"<<endl; //
a79660fb 230 percentage=(Double_t)(stat[3]*125)/fileDimension;
0b3c7dfc 231 fStat<<" Central Samples..........."<<(UInt_t)TMath::Ceil(stat[3]*10/8)<<" bytes "<<percentage<<"%"<<endl; //
a79660fb 232 percentage=(Double_t)(stat[4]*125)/fileDimension;
0b3c7dfc 233 fStat<<" Border Samples............"<<(UInt_t)TMath::Ceil(stat[4]*10/8)<<" bytes "<<percentage<<"%"<<endl; //
a79660fb 234 fStat.close();
2e9f335b 235 return 0;
236}
237////////////////////////////////////////////////////////////////////////////////////////
238Int_t AliTPCCompression::StoreTables(AliTPCHTable* table[],const Int_t NumTable){
a79660fb 239 //This method stores the tables in a sequence of binary file
2e9f335b 240 char filename[15];
241 ofstream fTable;
242 for(Int_t k=0;k<NumTable;k++){
30c1018e 243 sprintf(filename,"Table%d.dat",k);
244#ifndef __DECCXX
2e9f335b 245 fTable.open(filename,ios::binary);
30c1018e 246#else
247 fTable.open(filename);
248#endif
2e9f335b 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++){
a79660fb 254 UChar_t codeLen=table[k]->CodeLen()[i];
0b3c7dfc 255 // UInt_t code=(UInt_t)table[k]->Code()[i];
a79660fb 256 Double_t code=table[k]->Code()[i];
257 fTable.write((char*)(&codeLen),sizeof(UChar_t));
0b3c7dfc 258 //fTable.write((char*)(&code),sizeof(UInt_t));
a79660fb 259 fTable.write((char*)(&code),sizeof(Double_t));
2e9f335b 260 } //end for
261 fTable.close();
262 }//end for
263 return 0;
264}
265////////////////////////////////////////////////////////////////////////////////////////
09f6432c 266Int_t AliTPCCompression::CreateTableFormula(Double_t beta,UInt_t M,Int_t dim,Int_t Type){
9f992f70 267 // Type = 0 for Bunch length
268 // Type = 1 for Time Gap
0b3c7dfc 269 UInt_t freq;
9f992f70 270 Double_t sum=0;
271 Double_t min=10;
272 Double_t alpha=0;
bea6b2a4 273 Double_t a=0;
274 AliTPCHTable *table=new AliTPCHTable(dim);
9f992f70 275
276 freq=1;
bea6b2a4 277 Double_t freqArray[1024];
9f992f70 278 for(Int_t i=0;i<1024;i++){
bea6b2a4 279 freqArray[i]=0;
9f992f70 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)
bea6b2a4 286 freqArray[x]=TMath::Power((x+1),-beta)*TMath::Exp(-alpha*(x+1));
9f992f70 287 else
bea6b2a4 288 freqArray[x]=TMath::Power((x+1),-beta);
289 sum+=freqArray[x];
290 if (freqArray[x]<min)min=freqArray[x];
9f992f70 291 }//end for
292 if (fVerbose)
293 cout<<"Minimun Value "<<min<<endl;
bea6b2a4 294 a=1/sum;
9f992f70 295 if (fVerbose)
bea6b2a4 296 cout<<"a Value: "<<a<<endl;
9f992f70 297 for(Int_t x=0;x<dim;x++){
298 if (Type==0)//Bunch length
299 if (x>=3)//minimum bunch length
bea6b2a4 300 table->SetValFrequency(x,a*freqArray[x]*1000);
9f992f70 301 else
bea6b2a4 302 table->SetValFrequency(x,0);
9f992f70 303 else //Time table
bea6b2a4 304 table->SetValFrequency(x,a*freqArray[x]);
9f992f70 305 }
bea6b2a4 306 table->BuildHTable();
9f992f70 307 ofstream fTable;
308 char filename[15];
309 sprintf(filename,"Table%d.dat",Type);
c9c9614f 310#ifndef __DECCXX
9f992f70 311 fTable.open(filename,ios::binary);
c9c9614f 312#else
313 fTable.open(filename);
314#endif
bea6b2a4 315 Int_t dimTable=table->Size();
9f992f70 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++){
bea6b2a4 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));
9f992f70 324 } //end for
325 fTable.close();
bea6b2a4 326 delete table;
9f992f70 327 return 0;
328}
329////////////////////////////////////////////////////////////////////////////////////////
09f6432c 330Int_t AliTPCCompression::CreateTables(const char* fSource,Int_t NumTables){
a79660fb 331 //Tables manager
2e9f335b 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 */
a79660fb 340 Int_t n=10;// 10 bits per symbol
2e9f335b 341 AliTPCHTable ** table = new AliTPCHTable*[NumTables];
342 //The table is inizialized with the rigth number of rows
9f992f70 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 }
2e9f335b 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
c9bd9d3d 354
2e9f335b 355 for(Int_t i=0;i<NumTables;i++){
356 table[i]->CompleteTable(i);
357 }
c9bd9d3d 358
2e9f335b 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 }
a79660fb 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();
2e9f335b 375
376 if (fVerbose)
377 cout<<"Tables filled \n";
9f992f70 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
2e9f335b 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/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
433Int_t AliTPCCompression::RetrieveTables(AliTPCHTable* table[],Int_t NumTable){
a79660fb 434 //This method retrieve the Huffman tables from a sequence of binary files
2e9f335b 435 if (fVerbose)
436 cout<<"Retrieving tables from files \n";
0b3c7dfc 437 // UInt_t code;
a79660fb 438 Double_t code;
439 UChar_t codeLen;
2e9f335b 440 ifstream fTable;
1d98347a 441 char filename[256];
2e9f335b 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++){
a79660fb 444 Int_t dim;//this variable contains the table dimension
2e9f335b 445 sprintf(filename,"Table%d.dat",k);
30c1018e 446#ifndef __DECCXX
2e9f335b 447 fTable.open(filename,ios::binary);
30c1018e 448#else
449 fTable.open(filename);
450#endif
1d98347a 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 }
a79660fb 464 fTable.read((char*)(&dim),sizeof(Int_t));
2e9f335b 465 if (fVerbose)
a79660fb 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);
0b3c7dfc 471 // fTable.read((char*)(&code),sizeof(UInt_t));
a79660fb 472 fTable.read((char*)(&code),sizeof(Double_t));
0b3c7dfc 473 table[k]->SetCode(Mirror((UInt_t)code,codeLen),i);
2e9f335b 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}
9f992f70 482
483Int_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);
1d98347a 497 if(!fTable){
498 Error("CreateTablesFromTxtFiles", "File doesn't exist: %s", filename);
499 return 1;
500 }
9f992f70 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
2e9f335b 538////////////////////////////////////////////////////////////////////////////////////////
539/* COMPRESSION */
540////////////////////////////////////////////////////////////////////////////////////////
541
0b3c7dfc 542void AliTPCCompression::StoreValue(UInt_t val,UChar_t len){
a79660fb 543 //This method stores the value "val" of "len" bits into the internal buffer "fBuffer"
2e9f335b 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
0b3c7dfc 549 f.write((char*)(&fBuffer),sizeof(UInt_t));
2e9f335b 550 fFreeBitsBuffer=fDimBuffer;
551 fBuffer=0;
552 }
553 }//end if
554 else{ //val has to be splitted in two buffers
555 fBuffer=fBuffer<<fFreeBitsBuffer;
0b3c7dfc 556 UInt_t temp;
2e9f335b 557 temp=val;
558 temp=temp>>(len-fFreeBitsBuffer);
559 fBuffer=fBuffer|temp;
0b3c7dfc 560 f.write((char*)(&fBuffer),sizeof(UInt_t));
2e9f335b 561 fFreeBitsBuffer=fDimBuffer-(len-fFreeBitsBuffer);
562 val=val<<fFreeBitsBuffer;
563 val=val>>fFreeBitsBuffer;
564 fBuffer=val;
565 }//end else
566 return;
567}
568//////////////////////////////////////////////////////////////////////////////////////////////////
569void AliTPCCompression::Flush(){
a79660fb 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
2e9f335b 572 if(fFreeBitsBuffer<fDimBuffer){
573 fBuffer=fBuffer<<fFreeBitsBuffer;
0b3c7dfc 574 f.write((char*)(&fBuffer),sizeof(UInt_t));
2e9f335b 575 }//end if
576 return;
577}
578//////////////////////////////////////////////////////////////////////////////////////////////////
0b3c7dfc 579UInt_t AliTPCCompression::Mirror(UInt_t val,UChar_t len)const{
a79660fb 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
0b3c7dfc 582 UInt_t specular=0;
583 UInt_t mask=0x1;
584 UInt_t bit;
2e9f335b 585 for(Int_t i=0;i<len;i++){
a79660fb 586 bit=val&mask;
2e9f335b 587 bit=bit>>i;
588 specular=specular<<1;
589 specular=specular|bit;
a79660fb 590 mask=mask<<1;
2e9f335b 591 }
592 return specular;
593}
2e9f335b 594
595/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
596Int_t AliTPCCompression::CompressDataOptTables(Int_t NumTable,const char* fSource,const char* fDest){
a79660fb 597 //This method compress an Altro format file using a general set of tables stored as binary files to be provided
2e9f335b 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")
a79660fb 603 AliTPCHTable **table = new AliTPCHTable*[NumTable];
1d98347a 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 }
2e9f335b 610 //the output file is open
1d98347a 611 f.clear();
30c1018e 612#ifndef __DECCXX
2e9f335b 613 f.open(fDest,ios::binary|ios::out);
30c1018e 614#else
615 f.open(fDest,ios::out);
616#endif
2e9f335b 617 // Source file is open
3ea47630 618 AliAltroBuffer buff(fSource,0);
2e9f335b 619 //coded words are written into a file
a79660fb 620 Int_t numWords,padNum,rowNum,secNum=0;
0b3c7dfc 621 UInt_t storedWords=0;
a79660fb 622 Int_t value=0;
0b3c7dfc 623 UInt_t numPackets=0;
a79660fb 624 Double_t stat[5]={0.,0.,0.,0.,0.};
0b3c7dfc 625 UInt_t trailerNumbers=0;
a79660fb 626 Double_t numElem[5]={0,0,0,0,0};
627 Double_t fillWords=0.;
1d98347a 628 fStat.clear();
a79660fb 629 fStat.open("Statistics",ios::app);
630 fStat<<endl;
631 fStat<<"-------------------COMPRESSION STATISTICS----------"<<endl;
632 Int_t end=1;
3ea47630 633 while(buff.ReadTrailerBackward(numWords,padNum,rowNum,secNum)){
a79660fb 634 if(end){
635 fillWords=buff.GetFillWordsNum();
636 end=0;
2e9f335b 637 }//endif
638
a79660fb 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();
2e9f335b 644 }//end for
645 }//end if
646
a79660fb 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;
2e9f335b 652
a79660fb 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++;
2e9f335b 662 }
a79660fb 663 NextTable(value,nextTableType,bunchLen,count);
2e9f335b 664 }//end for
665 //computing the Time gap between two bunches
666 Int_t temp=0;
a79660fb 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;
2e9f335b 675 }//end for
676
a79660fb 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){
0b3c7dfc 685 //UInt_t val=(UInt_t)table[nextTableType]->Code()[value]; // val is the code
a79660fb 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]++;
0b3c7dfc 690 StoreValue((UInt_t)val,len);
a79660fb 691 storedWords++;
2e9f335b 692 }//end if
a79660fb 693 NextTable(value,nextTableType,bunchLen,count);
694 if(nextTableType==0){
0b3c7dfc 695 // UInt_t val=(UInt_t)table[1]->Code()[timeBin]; // val is the code
a79660fb 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]++;
0b3c7dfc 700 StoreValue((UInt_t)val,len);
701 // val=(UInt_t)table[nextTableType]->Code()[(bunchLen+2)]; // val is the code
a79660fb 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
0b3c7dfc 704 StoreValue((UInt_t)val,len);
a79660fb 705 stat[nextTableType]+=len;
706 numElem[nextTableType]++;
707 storedWords+=2;
2e9f335b 708 }
709 }//end for
710 //Trailer
a79660fb 711 StoreValue(numWords,10);
712 StoreValue(padNum,10);
713 StoreValue(rowNum,10);
714 StoreValue(secNum,9);
2e9f335b 715 StoreValue(1,1);
a79660fb 716 storedWords+=4;
717 trailerNumbers++;
2e9f335b 718 }//end while
a79660fb 719 StoreValue(numPackets,32);
2e9f335b 720 if(fVerbose)
a79660fb 721 cout<<"Number of strored packets: "<<numPackets<<endl;
2e9f335b 722 StoreValue(1,1);
723 //The last buffen cannot be completely full
724 Flush();
725 if(fVerbose)
a79660fb 726 cout<<"Number of stored words: "<<storedWords<<endl;
2e9f335b 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;
0b3c7dfc 733 Double_t dimension=(UInt_t)TMath::Ceil((stat[0]+stat[1]+stat[2]+stat[3]+stat[4])/8)+trailerNumbers*5;
a79660fb 734 fStat<<"Trailer Dimension in bytes......"<<trailerNumbers*5<<endl;
0b3c7dfc 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;
2e9f335b 737 /*
0b3c7dfc 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;
2e9f335b 745 */
a79660fb 746 fillWords=(fillWords+numElem[0]+numElem[1]+numElem[2]+numElem[3]+numElem[4]+trailerNumbers*4)*10/8;
0b3c7dfc 747 fStat<<"Original file dimension........."<<(UInt_t)fillWords<<endl;
2e9f335b 748
a79660fb 749 Double_t ratio=(dimension/fillWords)*100;
750 fStat<<"Compression ratio (Compressed/Uncompressed)..."<<ratio<<"%"<<endl;
751 fStat<<endl;
9f992f70 752 if (numElem[0])
0b3c7dfc 753 fStat<<"Bunch length size in bytes......"<<(UInt_t)TMath::Ceil(stat[0]/8)<<" Comppression.."<<(stat[0]/numElem[0])*10<<"%"<<endl;
9f992f70 754 if (numElem[1])
0b3c7dfc 755 fStat<<"Time gap size in bytes.........."<<(UInt_t)TMath::Ceil(stat[1]/8)<<" Comppression.."<<(stat[1]/numElem[1])*10<<"%"<<endl;
9f992f70 756 if (numElem[2]+numElem[3]+numElem[4])
0b3c7dfc 757 fStat<<"Amplitude values in bytes......."<<(UInt_t)TMath::Ceil((stat[2]+stat[3]+stat[4])/8)<<" Comppression.."<<
9f992f70 758 ((stat[2]+stat[3]+stat[4])/(numElem[2]+numElem[3]+numElem[4]))*10<<"%"<<endl;
759 if (numElem[2])
0b3c7dfc 760 fStat<<" One Samples in bytes............"<<(UInt_t)TMath::Ceil(stat[2]/8)<<" Comppression.."<<(stat[2]/numElem[2])*10<<"%"<<endl;
9f992f70 761 if (numElem[3])
0b3c7dfc 762 fStat<<" Central Samples size in bytes..."<<(UInt_t)TMath::Ceil(stat[3]/8)<<" Comppression.."<<(stat[3]/numElem[3])*10<<"%"<<endl;
9f992f70 763 if (numElem[4])
0b3c7dfc 764 fStat<<" Border Samples size in bytes...."<<(UInt_t)TMath::Ceil(stat[4]/8)<<" Comppression.."<<(stat[4]/numElem[4])*10<<"%"<<endl;
a79660fb 765 fStat<<endl;
766 fStat<<"Average number of bits per word"<<endl;
9f992f70 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;
a79660fb 777 fStat.close();
2e9f335b 778 return 0;
779}
780
781////////////////////////////////////////////////////////////////////////////////////////
782
783////////////////////////////////////////////////////////////////////////////////////////
784/* DECOMPRESSION */
785////////////////////////////////////////////////////////////////////////////////////////
c9bd9d3d 786
1d98347a 787Int_t AliTPCCompression::CreateTreesFromFile(AliTPCHNode *RootNode[],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;
0b3c7dfc 793 // UInt_t code;
a79660fb 794 Double_t code;
795 UChar_t codeLen;
2e9f335b 796 ifstream fTable;
09c9f31b 797 char filename[256];
2e9f335b 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
1d98347a 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 }
a79660fb 822 fTable.read((char*)(&dim),sizeof(Int_t));
2e9f335b 823 if (fVerbose)
a79660fb 824 cout<<"Table dimension: "<<dim<<endl;
2e9f335b 825 //loop over the words of one table
a79660fb 826 for(Int_t i=0;i<dim;i++){
827 fTable.read((char*)(&codeLen),sizeof(UChar_t));
0b3c7dfc 828 //fTable.read((char*)(&code),sizeof(UInt_t));
a79660fb 829 fTable.read((char*)(&code),sizeof(Double_t));
2e9f335b 830 node=RootNode[k];
a79660fb 831 for(Int_t j=1;j<=codeLen;j++){
0b3c7dfc 832 UInt_t bit,val=0;
833 val=(UInt_t)TMath::Power(2,codeLen-j);
834 bit=(UInt_t)code&val;
2e9f335b 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
a79660fb 851 if(codeLen){
2e9f335b 852 node->SetSymbol(i);
a79660fb 853 node->SetFrequency(codeLen);
2e9f335b 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
1d98347a 861 return 0;
2e9f335b 862}
863//////////////////////////////////////////////////////////////////////////////////////////////////
864void AliTPCCompression::DeleteHuffmanTree(AliTPCHNode* node){
865 //This function deletes all the nodes of an Huffman tree
a79660fb 866 //In an Huffman tree any internal node has always two children
2e9f335b 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//////////////////////////////////////////////////////////////////////////////////////////////////
875void AliTPCCompression::VisitHuffmanTree(AliTPCHNode* node){
a79660fb 876 //This function realizes an in order visit of a binary tree
2e9f335b 877 if (node){
878 cout<<node->GetSymbol()<<" "<<node->GetFrequency()<<endl;
879 VisitHuffmanTree(node->GetLeft());
880 VisitHuffmanTree(node->GetRight());
881 }
882}
883//////////////////////////////////////////////////////////////////////////////////////////////////
0b3c7dfc 884UInt_t AliTPCCompression::ReadWord(Int_t NumberOfBit){
a79660fb 885 //This method retrieves a word of a specific number of bits from the file through the internal buffer
0b3c7dfc 886 UInt_t result=0;
887 UInt_t bit=0;
2e9f335b 888 for (Int_t i=0;i<NumberOfBit;i++){
889 if (fReadBits==32){
0b3c7dfc 890 fPos-=sizeof(UInt_t);
2e9f335b 891 f.seekg(fPos);
0b3c7dfc 892 f.read((char*)(&fBuffer),sizeof(UInt_t));
2e9f335b 893 fReadBits=0;
894 }//end if
a8ffd46b 895 // UInt_t mask=0;
896 // mask=(UInt_t)TMath::Power(2,fReadBits);
897 UInt_t mask=(UInt_t)(1<<fReadBits);
2e9f335b 898 bit=fBuffer&mask;
899 bit=bit>>fReadBits;
900 fReadBits++;
901 bit=bit<<i;
a79660fb 902 result=result|bit;
2e9f335b 903 }//end for
a79660fb 904 return result;
2e9f335b 905}
906//////////////////////////////////////////////////////////////////////////////////////////////////
0b3c7dfc 907UInt_t AliTPCCompression::ReadWordBuffer(Int_t NumberOfBit){
c9bd9d3d 908 //This method retrieves a word of a specific number of bits from the file through the buffer
0b3c7dfc 909 UInt_t result=0;
910 UInt_t bit=0;
c9bd9d3d 911 for (Int_t i=0;i<NumberOfBit;i++){
912 if (fReadBits==32){
a8ffd46b 913 fPointBuffer--;
914 fBuffer=*fPointBuffer;
c9bd9d3d 915 fReadBits=0;
916 }//end if
a8ffd46b 917 bit=fBuffer&0x1;
c9bd9d3d 918 bit=bit<<i;
919 result=result|bit;
a8ffd46b 920 fReadBits++;
921 fBuffer=fBuffer>>1;
c9bd9d3d 922 }//end for
923 return result;
924}
925
a8ffd46b 926//////////////////////////////////////////////////////////////////////////////////////////////////
927inline UInt_t AliTPCCompression::ReadBitFromWordBuffer(){
928 //This method retrieves a word of a specific number of bits from the file through the buffer
929 UInt_t result=0;
930
931 if (fReadBits==32){
932 fPointBuffer--;
933 fBuffer=*fPointBuffer;
934 fReadBits=0;
935 }//end if
936 result=fBuffer&0x1;
937 fReadBits++;
938 fBuffer=fBuffer>>1;
939 return result;
940}
941
c9bd9d3d 942//////////////////////////////////////////////////////////////////////////////////////////////////
943void AliTPCCompression::ReadTrailer(Int_t &WordsNumber,Int_t &PadNumber,Int_t &RowNumber,Int_t &SecNumber,Bool_t Memory){
a79660fb 944 //It retrieves a trailer
c9bd9d3d 945 if(Memory){
a8ffd46b 946 ReadBitFromWordBuffer();
c9bd9d3d 947 SecNumber=ReadWordBuffer(9);
948 RowNumber=ReadWordBuffer(10);
949 PadNumber=ReadWordBuffer(10);
950 WordsNumber=ReadWordBuffer(10);
951 }
952 else{
953 ReadWord(1);
954 SecNumber=ReadWord(9);
955 RowNumber=ReadWord(10);
956 PadNumber=ReadWord(10);
957 WordsNumber=ReadWord(10);
958 }
2e9f335b 959 return;
960}
961//////////////////////////////////////////////////////////////////////////////////////////////////
a8ffd46b 962inline UInt_t AliTPCCompression::GetDecodedWordBuffer(AliTPCHNode* root){
a79660fb 963 //This method retrieves a decoded word.
2e9f335b 964 AliTPCHNode *node=root;
0b3c7dfc 965 UInt_t symbol=0;
2e9f335b 966 Bool_t decoded=0;
a8ffd46b 967
2e9f335b 968 while(!decoded){
a8ffd46b 969 UInt_t bit=ReadBitFromWordBuffer();
970 if(bit)
971 node=node->GetRight();
c9bd9d3d 972 else
a8ffd46b 973 node=node->GetLeft();
974 if (!(node->GetLeft())){
975 symbol=node->GetSymbol();
976 decoded=1;
977 }
978 }//end while
979 return symbol;
980}
981
982inline UInt_t AliTPCCompression::GetDecodedWord(AliTPCHNode* root){
983 //This method retrieves a decoded word.
984 AliTPCHNode *node=root;
985 UInt_t symbol=0;
986 Bool_t decoded=0;
987
988 while(!decoded){
989 UInt_t bit=ReadWord(1);
2e9f335b 990 if(bit)
991 node=node->GetRight();
992 else
993 node=node->GetLeft();
994 if (!(node->GetLeft())){
995 symbol=node->GetSymbol();
996 decoded=1;
997 }
998 }//end while
a8ffd46b 999
2e9f335b 1000 return symbol;
1001}
1002//////////////////////////////////////////////////////////////////////////////////////////////////
c9bd9d3d 1003
5fe3851e 1004Int_t AliTPCCompression::DecompressDataOptTables(Int_t NumTables,const char* fname, const char* fDest){
c9bd9d3d 1005 //This method decompress a file using separate Huffman tables
1006 if(fVerbose){
1007 cout<<" DECOMPRESSION:"<<endl;
1008 cout<<"Source File "<<fname<<" Destination File "<<fDest<<endl;
1009 }
1010 AliTPCHNode ** rootNode = new AliTPCHNode*[NumTables];
1d98347a 1011 for(Int_t i=0;i<NumTables;i++) rootNode[i] = NULL;
c9bd9d3d 1012 //Creation of the Huffman trees
1d98347a 1013 if (CreateTreesFromFile(rootNode,NumTables) != 0) {
1014 for(Int_t i=0;i<NumTables;i++) {
1015 if (rootNode[i]) DeleteHuffmanTree(rootNode[i]);
1016 }
1017 delete [] rootNode;
1018 return 1;
1019 }
1020 f.clear();
c9bd9d3d 1021#ifndef __DECCXX
2e9f335b 1022 f.open(fname,ios::binary|ios::in);
30c1018e 1023#else
1024 f.open(fname,ios::in);
1025#endif
1d98347a 1026 if(!f){
1027 Error("DecompressDataOptTables", "File doesn't exist:",fname);
1028 return -1;
1029 }
2e9f335b 1030 //to go to the end of the file
1031 f.seekg(0,ios::end);
1032 //to get the file dimension in byte
1033 fPos=f.tellg();
0b3c7dfc 1034 fPos-=sizeof(UInt_t);
2e9f335b 1035 f.seekg(fPos);
1036 fReadBits=0;
1037 fBuffer=0;
0b3c7dfc 1038 f.read((char*)(&fBuffer),sizeof(UInt_t));
2e9f335b 1039 Int_t bit=0;
0b3c7dfc 1040 UInt_t mask=0x1;
2e9f335b 1041 while(!bit){
a79660fb 1042 bit=fBuffer&mask;
1043 mask=mask<<1;
2e9f335b 1044 fReadBits++;
1045 }
0b3c7dfc 1046 UInt_t packetNumber=ReadWord(sizeof(UInt_t)*8);
c9bd9d3d 1047 if(fVerbose){
1048 cout<<"Number of Packect: "<<packetNumber<<endl;
1049 }
3ea47630 1050 AliAltroBuffer bufferFile(fDest,1);
0b3c7dfc 1051 UInt_t k=0;
1052 UInt_t wordsRead=0; //number of read coded words
a79660fb 1053 while(k<packetNumber){
1054 Int_t numWords,padNumber,rowNumber,secNumber=0;
c9bd9d3d 1055 ReadTrailer(numWords,padNumber,rowNumber,secNumber,kFALSE);
2e9f335b 1056 k++;
a79660fb 1057 wordsRead+=4;
1058 Int_t previousTime=-1;
1059 Int_t time=0;
1060 Int_t nextTableType=0;
1061 Int_t bunchLen=0;
1062 Int_t count=0;
1063 for(Int_t i=0;i<numWords;i++){
a8ffd46b 1064 UInt_t symbol=GetDecodedWord(rootNode[nextTableType]);
a79660fb 1065 wordsRead++;
2e9f335b 1066 //Time reconstruction
a79660fb 1067 if (nextTableType==1){
1068 if (previousTime!=-1){
1069 previousTime=symbol+previousTime+bunchLen;
2e9f335b 1070 }
a79660fb 1071 else previousTime=symbol;
1072 time=previousTime;
2e9f335b 1073 }
a79660fb 1074 if(nextTableType>1)
1075 bufferFile.FillBuffer(symbol);
1076 NextTable(symbol,nextTableType,bunchLen,count);
1077 if(nextTableType==0){
1078 bufferFile.FillBuffer(time);
1079 bufferFile.FillBuffer(bunchLen+2);
1080 bunchLen=0;
2e9f335b 1081 }
1082 }//end for
a79660fb 1083 bufferFile.WriteTrailer(numWords,padNumber,rowNumber,secNumber);
2e9f335b 1084 }//end while
c9bd9d3d 1085 if(fVerbose){
1086 cout<<"Number of decoded words:"<<wordsRead<<endl;
1087 }
2e9f335b 1088 f.close();
1089 //The trees are deleted
1090 for(Int_t j=0;j<NumTables;j++){
a79660fb 1091 DeleteHuffmanTree(rootNode[j]);
2e9f335b 1092 }//end for
c9bd9d3d 1093 delete [] rootNode;
2e9f335b 1094 return 0;
1095}
1096
c9bd9d3d 1097//////////////////////////////////////////////////////////////////////////////////////////////////
09f6432c 1098Int_t AliTPCCompression::Decompress(AliTPCHNode *RootNode[],Int_t /*NumTables*/,char* PointBuffer,UInt_t BufferSize,UShort_t out[],UInt_t &dim){
a79660fb 1099 //This method decompress a file using separate Huffman tables
c9bd9d3d 1100
a8ffd46b 1101 // fPointBuffer=((UInt_t *)PointBuffer)+(UInt_t)(BufferSize/4)-1;
1102 fPointBuffer=(UInt_t *)(PointBuffer+BufferSize-4);
2e9f335b 1103 fReadBits=0;
1104 fBuffer=0;
c9bd9d3d 1105
a8ffd46b 1106 fBuffer=*fPointBuffer;
2e9f335b 1107 Int_t bit=0;
2e9f335b 1108 while(!bit){
a8ffd46b 1109 bit=fBuffer&0x1;
1110 fBuffer=fBuffer>>1;
2e9f335b 1111 fReadBits++;
c9bd9d3d 1112 }//end while
0b3c7dfc 1113 UInt_t packetNumber=ReadWordBuffer(sizeof(UInt_t)*8); //32 bits
c9bd9d3d 1114 if (fVerbose){
1115 cout<<"First one has been found "<<endl;
1116 cout<<"Number of packets:"<<packetNumber<<endl;
1117 }//end if
0b3c7dfc 1118 UInt_t k=0;
1119 UInt_t wordsRead=0; //number of read coded words
a79660fb 1120 while(k<packetNumber){
1121 Int_t numWords,padNumber,rowNumber,secNumber=0;
c9bd9d3d 1122 ReadTrailer(numWords,padNumber,rowNumber,secNumber,kTRUE);
1123 out[dim]=numWords;
1124 dim++;
1125 out[dim]=padNumber;
1126 dim++;
1127 out[dim]=rowNumber;
1128 dim++;
1129 out[dim]=secNumber;
1130 dim++;
1131 //ftxt<<"S:"<<secNumber<<" R:"<<rowNumber<<" P:"<<padNumber<<" W:"<<numWords<<endl;
1132 // padDigits->SetPadID(padNumber,rowNumber,secNumber,DDL);
2e9f335b 1133 k++;
a79660fb 1134 wordsRead+=4;
1135 Int_t previousTime=-1;
1136 Int_t time=0;
1137 Int_t nextTableType=0;
1138 Int_t bunchLen=0;
1139 Int_t count=0;
c9bd9d3d 1140 Int_t timeDigit=0;
a79660fb 1141 for(Int_t i=0;i<numWords;i++){
a8ffd46b 1142 UInt_t symbol=GetDecodedWordBuffer(RootNode[nextTableType]);
a79660fb 1143 wordsRead++;
2e9f335b 1144 //Time reconstruction
a79660fb 1145 if (nextTableType==1){
1146 if (previousTime!=-1){
1147 previousTime=symbol+previousTime+bunchLen;
2e9f335b 1148 }
a79660fb 1149 else previousTime=symbol;
1150 time=previousTime;
c9bd9d3d 1151 out[dim]=bunchLen+2;
1152 dim++;
1153 out[dim]=time;
1154 dim++;
1155 timeDigit=time-bunchLen;
2e9f335b 1156 }
c9bd9d3d 1157 if(nextTableType>1){
c9bd9d3d 1158 //
1159 //ftxt<<symbol<<endl;
1160 out[dim]=symbol;
1161 dim++;
1162 timeDigit++;
1163 //padDigits->SetDigits(symbol,timeDigit);
1164 }
a79660fb 1165 NextTable(symbol,nextTableType,bunchLen,count);
1166 if(nextTableType==0){
c9bd9d3d 1167 //
c9bd9d3d 1168 //ftxt<<time<<endl;
1169 // ftxt<<(bunchLen+2)<<endl;
a79660fb 1170 bunchLen=0;
2e9f335b 1171 }
1172 }//end for
2e9f335b 1173 }//end while
2e9f335b 1174 return 0;
1175}
1176
c9bd9d3d 1177//////////////////////////////////////////////////////////////////////////////////////////////////
09f6432c 1178Int_t AliTPCCompression::DestroyTables(AliTPCHNode *RootNode[],Int_t NumTables){
c9bd9d3d 1179 //The trees are deleted
1180 for(Int_t j=0;j<NumTables;j++){
1181 DeleteHuffmanTree(RootNode[j]);
1182 }//end for
1183 if(fVerbose)
1184 cout<<"Huffman trees destroyed"<<endl;
1185 return 0;
1186}
1187//////////////////////////////////////////////////////////////////////////////////////////////////
2e9f335b 1188
a79660fb 1189void AliTPCCompression::ReadAltroFormat(char* fileOut,char* fileIn)const{
1190 //This method creates a text file containing the same information stored in
1191 //an Altro file. The information in the text file is organized pad by pad and
1192 //and for each pad it consists in a sequence of bunches (Bunch length +2,
1193 //Time bin of the last amplitude sample in the bunch, amplitude values)
1194 //It is used mainly for debugging
2e9f335b 1195 ofstream ftxt(fileOut);
3ea47630 1196 AliAltroBuffer buff(fileIn,0);
a79660fb 1197 Int_t numWords,padNum,rowNum,secNum=0;
1198 Int_t value=0;
9f992f70 1199 if (fVerbose) cout<<"Creating a txt file from an Altro Format file"<<endl;
3ea47630 1200 while(buff.ReadTrailerBackward(numWords,padNum,rowNum,secNum)){
9f992f70 1201 ftxt<<"S:"<<secNum<<" R:"<<rowNum<<" P:"<<padNum<<" W:"<<numWords<<endl;
a79660fb 1202 if (numWords%4){
1203 for(Int_t j=0;j<(4-numWords%4);j++){
1204 value=buff.GetNextBackWord();
2e9f335b 1205 }//end for
1206 }//end if
a79660fb 1207 for(Int_t i=0;i<numWords;i++){
1208 value=buff.GetNextBackWord();
1209 ftxt<<value<<endl;
2e9f335b 1210 }//end for
1211 }//end while
1212 ftxt.close();
1213 return;
1214}
1215
1216//////////////////////////////////////////////////////////////////////////////////////////