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