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