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