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