1 /**************************************************************************
2 * Copyright(c) 1998-2003, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
16 #include <TObjArray.h>
17 #include "Riostream.h"
19 #include "AliTPCCompression.h"
20 #include "AliTPCBuffer160.h"
21 #include "AliTPCHuffman.h"
23 ClassImp(AliTPCCompression)
24 //////////////////////////////////////////////////////////////////////////////////////////////////
25 AliTPCCompression::AliTPCCompression(){
26 fDimBuffer=sizeof(ULong_t)*8;
27 fFreeBitsBuffer=fDimBuffer;
35 //////////////////////////////////////////////////////////////////////////////////////////////////
36 AliTPCCompression::AliTPCCompression(const AliTPCCompression &source){
37 this->fDimBuffer=source.fDimBuffer;
38 this->fFreeBitsBuffer=source.fFreeBitsBuffer;
39 this->fReadBits=source.fReadBits;
40 this->fPos=source.fPos;
41 this->fBuffer=source.fBuffer;
42 this->fVerbose=source.fVerbose;
43 this->fFillWords=source.fFillWords;
46 //////////////////////////////////////////////////////////////////////////////////////////////////
47 AliTPCCompression& AliTPCCompression::operator=(const AliTPCCompression &source){
48 this->fDimBuffer=source.fDimBuffer;
49 this->fFreeBitsBuffer=source.fFreeBitsBuffer;
50 this->fReadBits=source.fReadBits;
51 this->fPos=source.fPos;
52 this->fBuffer=source.fBuffer;
53 this->fVerbose=source.fVerbose;
54 this->fFillWords=source.fFillWords;
57 //////////////////////////////////////////////////////////////////////////////////////////////////
58 void AliTPCCompression::NextTable(Int_t Val,Int_t &NextTableType,Int_t &BunchLen,Int_t &Count){
61 0==> Bunch length value
67 switch (NextTableType){
74 if (BunchLen==1)NextTableType=2;
87 if (Count==(BunchLen-1)){
107 /////////////////////////////////////////////////////////////////////////////////////////////////////
109 /////////////////////////////////////////////////////////////////////////////////////////////////////
111 Int_t AliTPCCompression::FillTables(const char* fSource,AliTPCHTable* table[],const Int_t NumTables){
112 //This method is used to compute the frequencies of the symbols in the source file
113 AliTPCBuffer160 Buff(fSource,0);
114 ULong_t CountWords=0;
115 ULong_t CountTrailer=0;
116 Int_t NumWords,PadNum,RowNum,SecNum=0;
118 ULong_t Stat[5]={0,0,0,0,0};
121 while(Buff.ReadTrailerBackward(NumWords,PadNum,RowNum,SecNum) !=-1 ){
123 EndFill=Buff.GetFillWordsNum();
128 fFillWords+=4-NumWords%4;
129 for(Int_t j=0;j<(4-NumWords%4);j++){
130 Value=Buff.GetNextBackWord();
137 for(Int_t i=0;i<345;i++)TimePos[i]=0;
138 for(Int_t i=0;i<1024;i++)Packet[i]=0;
140 Int_t NextTableType=0;
143 for(Int_t i=0;i<NumWords;i++){
144 Value=Buff.GetNextBackWord();
146 if(NextTableType==1){
150 NextTable(Value,NextTableType,BunchLen,Count);
152 //computing the Time gap between two bunches
155 Int_t PreviousTime=Packet[TimePos[Tp]];
156 for(Int_t i=Tp-1;i>=0;i--){
157 Int_t TimPos=TimePos[i];
158 Int_t BunchLen=Packet[TimPos-1]-2;
160 Packet[TimPos]=Packet[TimPos]-PreviousTime-BunchLen;
166 for(Int_t i=0;i<NumWords;i++){
168 table[NextTableType]->SetFrequency(Value);
169 Stat[NextTableType]++;
170 NextTable(Value,NextTableType,BunchLen,Count);
174 cout<<"Number of words: "<<CountWords<<endl;
175 cout<<"Number of trailers: "<<CountTrailer<<endl;
176 cout<<"Number of fill words "<<fFillWords+EndFill<<endl;
177 cout<<"Total number of words: "<<CountWords+CountTrailer*4+fFillWords<<endl;
179 stat.open("Statistics");
180 stat<<"Number of words:..........................................."<<CountWords<<endl;
181 stat<<"Number of trailers (4 10 bits words in each one)..........."<<CountTrailer<<endl;
182 stat<<"Number of fill words:......................................"<<fFillWords+EndFill<<endl;
183 stat<<"Total number of words:....................................."<<CountWords+CountTrailer*4+fFillWords+EndFill<<endl;
184 stat<<"-----------------------------------------"<<endl;
185 stat<<"Number of Bunches............."<<Stat[0]<<endl;
186 stat<<"Number of Time bin............"<<Stat[1]<<endl;
187 stat<<"Number of One Samples Bunch..."<<Stat[2]<<endl;
188 stat<<"Number of Central Samples....."<<Stat[3]<<endl;
189 stat<<"Number of Border Samples......"<<Stat[4]<<endl;
190 stat<<"-----------------------------------------"<<endl;
191 ULong_t FileDimension=(ULong_t)TMath::Ceil(double((CountTrailer*4+CountWords+fFillWords+EndFill)*10/8));
192 stat<<"Total file Size in bytes.."<<FileDimension<<endl;
193 Double_t Percentage=TMath::Ceil((fFillWords+EndFill)*125)/FileDimension;
194 stat<<"Fill Words................"<<(ULong_t)TMath::Ceil((fFillWords+EndFill)*10/8)<<" bytes "<<Percentage<<"%"<<endl;
195 Percentage=(Double_t)CountTrailer*500/FileDimension;
196 stat<<"Trailer..................."<<CountTrailer*5<<" bytes "<<Percentage<<"%"<<endl;
198 Percentage=(Double_t)((Stat[0]+Stat[1]+Stat[2]+Stat[3]+Stat[4])) *125/FileDimension;
199 stat<<"Data......................"<<(ULong_t)TMath::Ceil((Stat[0]+Stat[1]+Stat[2]+Stat[3]+Stat[4])*10/8)<<" bytes "<<Percentage<<"%"<<endl;
201 Percentage=(Double_t)(Stat[0]*125)/FileDimension;
202 stat<<"Bunch....................."<<(ULong_t)TMath::Ceil(Stat[0]*10/8)<<" bytes "<<Percentage<<"%"<<endl; //
203 Percentage=(Double_t)(Stat[1]*125)/FileDimension;
204 stat<<"Time......................"<<(ULong_t)TMath::Ceil(Stat[1]*10/8)<<" bytes "<<Percentage<<"%"<<endl; //
207 Percentage=(Double_t)((Stat[2]+Stat[3]+Stat[4])) *125/FileDimension;
208 stat<<"Amplitude values.........."<<(ULong_t)TMath::Ceil((Stat[2]+Stat[3]+Stat[4])*10/8)<<" bytes "<<Percentage<<"%"<<endl;
209 Percentage=(Double_t)(Stat[2]*125)/FileDimension;
210 stat<<" One Samples..............."<<(ULong_t)TMath::Ceil(Stat[2]*10/8)<<" bytes "<<Percentage<<"%"<<endl; //
211 Percentage=(Double_t)(Stat[3]*125)/FileDimension;
212 stat<<" Central Samples..........."<<(ULong_t)TMath::Ceil(Stat[3]*10/8)<<" bytes "<<Percentage<<"%"<<endl; //
213 Percentage=(Double_t)(Stat[4]*125)/FileDimension;
214 stat<<" Border Samples............"<<(ULong_t)TMath::Ceil(Stat[4]*10/8)<<" bytes "<<Percentage<<"%"<<endl; //
218 ////////////////////////////////////////////////////////////////////////////////////////
219 Int_t AliTPCCompression::StoreTables(AliTPCHTable* table[],const Int_t NumTable){
222 for(Int_t k=0;k<NumTable;k++){
223 sprintf(filename,"Table%d.dat",k);
224 fTable.open(filename,ios::binary);
225 Int_t dim=table[k]->Size();
226 //Table dimension is written into a file
227 fTable.write((char*)(&dim),sizeof(Int_t));
228 //One table is written into a file
229 for(Int_t i=0;i<dim;i++){
230 UChar_t CodeLen=table[k]->CodeLen()[i];
231 // ULong_t Code=(ULong_t)table[k]->Code()[i];
232 Double_t Code=table[k]->Code()[i];
233 fTable.write((char*)(&CodeLen),sizeof(UChar_t));
234 //fTable.write((char*)(&Code),sizeof(ULong_t));
235 fTable.write((char*)(&Code),sizeof(Double_t));
241 ////////////////////////////////////////////////////////////////////////////////////////
242 Int_t AliTPCCompression::CreateTables(const char* fSource,const Int_t NumTables){
243 Int_t n=10;// 10 bits per symbol
246 0==> Bunch length values
252 AliTPCHTable ** table = new AliTPCHTable*[NumTables];
253 //The table is inizialized with the rigth number of rows
254 for(Int_t i=0;i<NumTables;i++){table[i]=new AliTPCHTable((Int_t)(TMath::Power(2,n)));}
255 //The frequencies are calculated and the tables are filled
257 cout<<"Filling tables...\n";
258 //The get the frequencies
259 FillTables(fSource,table,NumTables);
261 //This part will be used in the table optimization phase
263 for(Int_t i=0;i<NumTables;i++){
264 table[i]->CompleteTable(i);
268 cout<<"Entropy of Bunch length table........."<<table[0]->GetEntropy()<<endl;
269 cout<<"Entropy of Time bin table............."<<table[1]->GetEntropy()<<endl;
270 cout<<"Entropy of one Sample bunch table....."<<table[2]->GetEntropy()<<endl;
271 cout<<"Entropy of Central Sample table......."<<table[3]->GetEntropy()<<endl;
272 cout<<"Entropy Border Samples table.........."<<table[4]->GetEntropy()<<endl;
274 stat.open("Statistics",ios::app);
276 stat<<"----------------- ENTROPY for castomized tables --------------------------"<<endl;
277 stat<<"Entropy of Bunch length table......."<<table[0]->GetEntropy()<<endl;
278 stat<<"Entropy of Time bin table..........."<<table[1]->GetEntropy()<<endl;
279 stat<<"Entropy of one Sample bunch table..."<<table[2]->GetEntropy()<<endl;
280 stat<<"Entropy of Central Sample table....."<<table[3]->GetEntropy()<<endl;
281 stat<<"Entropy Border Samples table........"<<table[4]->GetEntropy()<<endl;
285 cout<<"Tables filled \n";
286 //Tables are saved in a sequence of text file and using the macro Histo.C is it possible to get
287 //a series of histograms rappresenting the frequency distribution
288 table[0]->StoreFrequencies("BunchLenFreq.txt");
289 table[1]->StoreFrequencies("TimeFreq.txt");
290 table[2]->StoreFrequencies("Sample1Freq.txt");
291 table[3]->StoreFrequencies("SCentralFreq.txt");
292 table[4]->StoreFrequencies("SBorderFreq.txt");
294 cout<<"Creating Tables..\n";
295 //One Huffman tree is created for each table starting from the frequencies of the symbols
296 for(Int_t i=0;i<NumTables;i++){
297 table[i]->BuildHTable();
299 cout<<"Number of elements inside the table:"<<table[i]->GetWordsNumber();
302 cout<<" (Bunch Length)"<<endl;
306 cout<<" (Time Bin)"<<endl;
310 cout<<" (1 Samples Bunch)"<<endl;
314 cout<<" (Central Samples)"<<endl;
318 cout<<" (Border Samples)"<<endl;
322 table[i]->PrintTable();
325 //The tables are saved ad binary files
326 StoreTables(table,NumTables);
327 //The tables stored in memory are deleted;
328 for(Int_t i=0;i<NumTables;i++)delete table[i];
332 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
333 Int_t AliTPCCompression::RetrieveTables(AliTPCHTable* table[],Int_t NumTable){
335 cout<<"Retrieving tables from files \n";
341 //The following for loop is used to generate the Huffman trees acording to the tables
342 for(Int_t k=0;k<NumTable;k++){
343 Int_t Dim;//this variable contains the table dimension
344 sprintf(filename,"Table%d.dat",k);
345 fTable.open(filename,ios::binary);
346 fTable.read((char*)(&Dim),sizeof(Int_t));
348 cout<<"Table dimension: "<<Dim<<endl;
349 table[k]=new AliTPCHTable(Dim);
350 for(Int_t i=0;i<Dim;i++){
351 fTable.read((char*)(&CodeLen),sizeof(UChar_t));
352 table[k]->SetCodeLen(CodeLen,i);
353 // fTable.read((char*)(&Code),sizeof(ULong_t));
354 fTable.read((char*)(&Code),sizeof(Double_t));
355 table[k]->SetCode(Mirror((ULong_t)Code,CodeLen),i);
360 cout<<"Trees generated \n";
361 //At this point the trees are been built
364 ////////////////////////////////////////////////////////////////////////////////////////
366 ////////////////////////////////////////////////////////////////////////////////////////
368 void AliTPCCompression::StoreValue(ULong_t val,UChar_t len){
369 if (len<=fFreeBitsBuffer){ // val is not splitted in two buffer
370 fFreeBitsBuffer-=len;
371 fBuffer=fBuffer<<len;
373 if(!fFreeBitsBuffer){ // if the buffer is full it is written into a file
374 f.write((char*)(&fBuffer),sizeof(ULong_t));
375 fFreeBitsBuffer=fDimBuffer;
379 else{ //val has to be splitted in two buffers
380 fBuffer=fBuffer<<fFreeBitsBuffer;
383 temp=temp>>(len-fFreeBitsBuffer);
384 fBuffer=fBuffer|temp;
385 f.write((char*)(&fBuffer),sizeof(ULong_t));
386 fFreeBitsBuffer=fDimBuffer-(len-fFreeBitsBuffer);
387 val=val<<fFreeBitsBuffer;
388 val=val>>fFreeBitsBuffer;
393 //////////////////////////////////////////////////////////////////////////////////////////////////
394 void AliTPCCompression::Flush(){
395 //The last buffen cannot be completely full
396 if(fFreeBitsBuffer<fDimBuffer){
397 fBuffer=fBuffer<<fFreeBitsBuffer;
398 f.write((char*)(&fBuffer),sizeof(ULong_t));
402 //////////////////////////////////////////////////////////////////////////////////////////////////
403 ULong_t AliTPCCompression::Mirror(ULong_t val,UChar_t len){
407 for(Int_t i=0;i<len;i++){
410 specular=specular<<1;
411 specular=specular|bit;
416 //////////////////////////////////////////////////////////////////////////////////////////////////
417 Int_t AliTPCCompression::CompressData(AliTPCHTable* table[],Int_t NumTable,const char* fSource,const char* fDest){
418 cout<<" COMPRESSION "<<endl;
419 cout<<"compression of the file "<<fSource<<" Output File: "<<fDest<<endl;
420 //the output file is open
421 f.open(fDest,ios::binary|ios::out);
422 //Tables are written into the output file
423 for(Int_t k=0;k<NumTable;k++){
424 Int_t dim=table[k]->Size();
425 //Table dimension is written into a file
426 f.write((char*)(&dim),sizeof(Int_t));
427 //One table is written into a file
428 for(Int_t i=0;i<dim;i++){
429 UChar_t CodeLen=table[k]->CodeLen()[i];
430 ULong_t Code=(ULong_t)table[k]->Code()[i];
431 f.write((char*)(&CodeLen),sizeof(UChar_t));
432 f.write((char*)(&Code),sizeof(ULong_t));
436 // Source file is open
437 AliTPCBuffer160 Buff(fSource,0);
438 //coded words are written into the output file
439 Int_t NumWords,PadNum,RowNum,SecNum=0;
440 ULong_t StoredWords=0;
443 while(Buff.ReadTrailerBackward(NumWords,PadNum,RowNum,SecNum) !=-1 ){
446 for(Int_t j=0;j<(4-NumWords%4);j++){
447 Value=Buff.GetNextBackWord();
454 for(Int_t i=0;i<345;i++)TimePos[i]=0;
455 for(Int_t i=0;i<1024;i++)Packet[i]=0;
457 Int_t NextTableType=0;
460 for(Int_t i=0;i<NumWords;i++){
461 Value=Buff.GetNextBackWord();
463 if(NextTableType==1){
467 NextTable(Value,NextTableType,BunchLen,Count);
469 //computing the Time gap between two bunches
472 Int_t PreviousTime=Packet[TimePos[Tp]];
473 for(Int_t i=Tp-1;i>=0;i--){
474 Int_t TimPos=TimePos[i];
475 Int_t BunchLen=Packet[TimPos-1]-2;
477 Packet[TimPos]=Packet[TimPos]-PreviousTime-BunchLen;
484 //All the words for one pad are compressed and stored in the compress file
485 for(Int_t i=0;i<NumWords;i++){
487 if(NextTableType==1)TimeBin=Value;
489 // ULong_t val=(ULong_t)table[NextTableType]->Code()[Value]; // val is the code
490 Double_t val=table[NextTableType]->Code()[Value]; // val is the code
491 UChar_t len=table[NextTableType]->CodeLen()[Value]; // len is the length (number of bits)of val
492 StoreValue(Mirror((ULong_t)val,len),len);
495 NextTable(Value,NextTableType,BunchLen,Count);
496 if(NextTableType==0){
497 // ULong_t val=(ULong_t)table[1]->Code()[TimeBin]; // val is the code
498 Double_t val=table[1]->Code()[TimeBin]; // val is the code
499 UChar_t len=table[1]->CodeLen()[TimeBin]; // len is the length (number of bits)of val
500 StoreValue(Mirror((ULong_t)val,len),len);
501 //val=(ULong_t)table[NextTableType]->Code()[(BunchLen+2)]; // val is the code
502 val=table[NextTableType]->Code()[(BunchLen+2)]; // val is the code
503 len=table[NextTableType]->CodeLen()[(BunchLen+2)]; // len is the length (number of bits)of val
504 StoreValue(Mirror((ULong_t)val,len),len);
509 StoreValue(NumWords,10);
510 StoreValue(PadNum,10);
511 StoreValue(RowNum,10);
512 StoreValue(SecNum,9);
516 StoreValue(NumPacket,32);
517 cout<<"Number of strored packet: "<<NumPacket<<endl;
519 //The last buffen cannot be completely full
521 cout<<"Number of stored words: "<<StoredWords<<endl;
526 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
527 Int_t AliTPCCompression::CompressDataOptTables(Int_t NumTable,const char* fSource,const char* fDest){
529 cout<<" BackWord COMPRESSION "<<endl;
530 cout<<"compression of the file "<<fSource<<" Output File: "<<fDest<<endl;
532 //Tables are read from the files (Each codeword has been "Mirrored")
533 AliTPCHTable ** table = new AliTPCHTable*[NumTable];
534 RetrieveTables(table,NumTable);
535 //the output file is open
536 f.open(fDest,ios::binary|ios::out);
537 // Source file is open
538 AliTPCBuffer160 Buff(fSource,0);
539 //coded words are written into a file
540 Int_t NumWords,PadNum,RowNum,SecNum=0;
541 ULong_t StoredWords=0;
544 Double_t Stat[5]={0.,0.,0.,0.,0.};
545 ULong_t TrailerNumber=0;
546 Double_t NumElem[5]={0,0,0,0,0};
547 Double_t FillWords=0.;
548 stat.open("Statistics",ios::app);
550 stat<<"-------------------COMPRESSION STATISTICS----------"<<endl;
552 while(Buff.ReadTrailerBackward(NumWords,PadNum,RowNum,SecNum) !=-1 ){
554 FillWords=Buff.GetFillWordsNum();
560 FillWords+=4-NumWords%4;
561 for(Int_t j=0;j<(4-NumWords%4);j++){
562 Value=Buff.GetNextBackWord();
569 for(Int_t i=0;i<345;i++)TimePos[i]=0;
570 for(Int_t i=0;i<1024;i++)Packet[i]=0;
572 Int_t NextTableType=0;
575 for(Int_t i=0;i<NumWords;i++){
576 Value=Buff.GetNextBackWord();
578 if(NextTableType==1){
582 NextTable(Value,NextTableType,BunchLen,Count);
584 //computing the Time gap between two bunches
587 Int_t PreviousTime=Packet[TimePos[Tp]];
588 for(Int_t i=Tp-1;i>=0;i--){
589 Int_t TimPos=TimePos[i];
590 Int_t BunchLen=Packet[TimPos-1]-2;
592 Packet[TimPos]=Packet[TimPos]-PreviousTime-BunchLen;
600 for(Int_t i=0;i<NumWords;i++){
602 if(NextTableType==1)TimeBin=Value;
604 //ULong_t val=(ULong_t)table[NextTableType]->Code()[Value]; // val is the code
605 Double_t val=table[NextTableType]->Code()[Value]; // val is the code
606 UChar_t len=table[NextTableType]->CodeLen()[Value]; // len is the length (number of bits)of val
607 Stat[NextTableType]+=len;
608 NumElem[NextTableType]++;
609 StoreValue((ULong_t)val,len);
612 NextTable(Value,NextTableType,BunchLen,Count);
613 if(NextTableType==0){
614 // ULong_t val=(ULong_t)table[1]->Code()[TimeBin]; // val is the code
615 Double_t val=table[1]->Code()[TimeBin]; // val is the code
616 UChar_t len=table[1]->CodeLen()[TimeBin]; // len is the length (number of bits)of val
619 StoreValue((ULong_t)val,len);
620 // val=(ULong_t)table[NextTableType]->Code()[(BunchLen+2)]; // val is the code
621 val=table[NextTableType]->Code()[(BunchLen+2)]; // val is the code
622 len=table[NextTableType]->CodeLen()[(BunchLen+2)]; // len is the length (number of bits)of val
623 StoreValue((ULong_t)val,len);
624 Stat[NextTableType]+=len;
625 NumElem[NextTableType]++;
630 StoreValue(NumWords,10);
631 StoreValue(PadNum,10);
632 StoreValue(RowNum,10);
633 StoreValue(SecNum,9);
638 StoreValue(NumPacket,32);
640 cout<<"Number of strored packet: "<<NumPacket<<endl;
642 //The last buffen cannot be completely full
645 cout<<"Number of stored words: "<<StoredWords<<endl;
648 for(Int_t i=0;i<NumTable;i++){
652 Double_t dimension=(ULong_t)TMath::Ceil((Stat[0]+Stat[1]+Stat[2]+Stat[3]+Stat[4])/8)+TrailerNumber*5;
653 stat<<"Trailer Dimension in bytes......"<<TrailerNumber*5<<endl;
654 stat<<"Data Dimension in bytes........."<<(ULong_t)TMath::Ceil((Stat[0]+Stat[1]+Stat[2]+Stat[3]+Stat[4])/8)<<endl;
655 stat<<"Compressed file dimension......."<<(ULong_t)dimension<<endl;
657 stat<<(ULong_t)TrailerNumber<<endl;
658 stat<<(ULong_t)FillWords<<endl;
659 stat<<(ULong_t)NumElem[0]<<endl;
660 stat<<(ULong_t)NumElem[1]<<endl;
661 stat<<(ULong_t)NumElem[2]<<endl;
662 stat<<(ULong_t)NumElem[3]<<endl;
663 stat<<(ULong_t)NumElem[4]<<endl;
665 FillWords=(FillWords+NumElem[0]+NumElem[1]+NumElem[2]+NumElem[3]+NumElem[4]+TrailerNumber*4)*10/8;
666 stat<<"Original file dimension........."<<(ULong_t)FillWords<<endl;
668 Double_t ratio=(dimension/FillWords)*100;
669 stat<<"Compression ratio (Compressed/Uncompressed)..."<<ratio<<"%"<<endl;
671 stat<<"Bunch length size in bytes......"<<(ULong_t)TMath::Ceil(Stat[0]/8)<<" Comppression.."<<(Stat[0]/NumElem[0])*10<<"%"<<endl;
673 stat<<"Time gap size in bytes.........."<<(ULong_t)TMath::Ceil(Stat[1]/8)<<" Comppression.."<<(Stat[1]/NumElem[1])*10<<"%"<<endl;
674 stat<<"Amplitude values in bytes......."<<(ULong_t)TMath::Ceil((Stat[2]+Stat[3]+Stat[4])/8)<<" Comppression.."<<
675 ((Stat[2]+Stat[3]+Stat[4])/(NumElem[2]+NumElem[3]+NumElem[4]))*10<<"%"<<endl;
676 stat<<" One Samples in bytes............"<<(ULong_t)TMath::Ceil(Stat[2]/8)<<" Comppression.."<<(Stat[2]/NumElem[2])*10<<"%"<<endl;
677 stat<<" Central Samples size in bytes..."<<(ULong_t)TMath::Ceil(Stat[3]/8)<<" Comppression.."<<(Stat[3]/NumElem[3])*10<<"%"<<endl;
678 stat<<" Border Samples size in bytes...."<<(ULong_t)TMath::Ceil(Stat[4]/8)<<" Comppression.."<<(Stat[4]/NumElem[4])*10<<"%"<<endl;
680 stat<<"Average number of bits per word"<<endl;
681 stat<<"Bunch length ......"<<Stat[0]/NumElem[0]<<endl;
682 stat<<"Time gap .........."<<Stat[1]/NumElem[1]<<endl;
683 stat<<"One Samples........"<<Stat[2]/NumElem[2]<<endl;
684 stat<<"Central Samples ..."<<Stat[3]/NumElem[3]<<endl;
685 stat<<"Border Samples....."<<Stat[4]/NumElem[4]<<endl;
690 ////////////////////////////////////////////////////////////////////////////////////////
692 ////////////////////////////////////////////////////////////////////////////////////////
694 ////////////////////////////////////////////////////////////////////////////////////////
695 void AliTPCCompression::CreateTrees(AliTPCHNode *RootNode[],const Int_t NumTables){
696 //The first part of the compressed file cotains the tables
697 //The following for loop is used to generate the Huffman trees acording to the tables
699 cout<<"Creating the Huffman trees \n";
704 //loop over the numbero of tables
705 for(Int_t k=0;k<NumTables;k++){
706 RootNode[k]=new AliTPCHNode(); //RootNode is the root of the tree
707 Int_t Dim;//this variable contains the table dimension
708 f.read((char*)(&Dim),sizeof(Int_t));
710 cout<<"Table dimension: "<<Dim<<endl;
711 //loop over the words of a table
712 for(Int_t i=0;i<Dim;i++){
713 f.read((char*)(&CodeLen),sizeof(UChar_t));
714 //f.read((char*)(&Code),sizeof(ULong_t));
715 f.read((char*)(&Code),sizeof(Double_t));
717 for(Int_t j=1;j<=CodeLen;j++){
719 val=(ULong_t)TMath::Power(2,CodeLen-j);
720 bit=(ULong_t)Code&val;
721 AliTPCHNode *temp=node;
723 node=node->GetRight();
725 node=new AliTPCHNode();
726 temp->SetRight(node);
730 node=node->GetLeft();
732 node=new AliTPCHNode();
739 node->SetFrequency(CodeLen);
741 //cout<<node->GetSymbol()<<" "<<(Int_t)node->GetFrequency()<<endl;
745 cout<<"Trees generated \n";
746 //At this point the trees are been built
748 //////////////////////////////////////////////////////////////////////////////////////////////////
749 void AliTPCCompression::CreateTreesFromFile(AliTPCHNode *RootNode[],const Int_t NumTables){
751 cout<<"Creating the Huffman trees \n";
758 //The following for loop is used to generate the Huffman trees acording to the tables
759 //loop over the tables
760 for(Int_t k=0;k<NumTables;k++){
761 RootNode[k]=new AliTPCHNode(); //RootNode is the root of the tree
762 Int_t Dim=0;//this variable contains the table dimension
763 sprintf(filename,"Table%d.dat",k);
764 fTable.open(filename,ios::binary);
765 fTable.read((char*)(&Dim),sizeof(Int_t));
767 cout<<"Table dimension: "<<Dim<<endl;
768 //loop over the words of one table
769 for(Int_t i=0;i<Dim;i++){
770 fTable.read((char*)(&CodeLen),sizeof(UChar_t));
771 //fTable.read((char*)(&Code),sizeof(ULong_t));
772 fTable.read((char*)(&Code),sizeof(Double_t));
774 for(Int_t j=1;j<=CodeLen;j++){
776 val=(ULong_t)TMath::Power(2,CodeLen-j);
777 bit=(ULong_t)Code&val;
778 AliTPCHNode *temp=node;
780 node=node->GetRight();
782 node=new AliTPCHNode();
783 temp->SetRight(node);
787 node=node->GetLeft();
789 node=new AliTPCHNode();
796 node->SetFrequency(CodeLen);
802 cout<<"Trees generated \n";
803 //At this point the trees are been built
805 //////////////////////////////////////////////////////////////////////////////////////////////////
806 void AliTPCCompression::DeleteHuffmanTree(AliTPCHNode* node){
807 //This function deletes all the nodes of an Huffman tree
808 //In an Huffman tree any internal node has always two children
810 DeleteHuffmanTree(node->GetLeft());
811 DeleteHuffmanTree(node->GetRight());
812 // cout<<node->GetSymbol()<<" "<<(Int_t)node->GetFrequency()<<endl;
816 //////////////////////////////////////////////////////////////////////////////////////////////////
817 void AliTPCCompression::VisitHuffmanTree(AliTPCHNode* node){
818 //This function realizes an in order visit of a binary tree
820 cout<<node->GetSymbol()<<" "<<node->GetFrequency()<<endl;
821 VisitHuffmanTree(node->GetLeft());
822 VisitHuffmanTree(node->GetRight());
825 //////////////////////////////////////////////////////////////////////////////////////////////////
826 ULong_t AliTPCCompression::ReadWord(Int_t NumberOfBit){
829 for (Int_t i=0;i<NumberOfBit;i++){
831 fPos-=sizeof(ULong_t);
833 f.read((char*)(&fBuffer),sizeof(ULong_t));
837 mask=(ULong_t)TMath::Power(2,fReadBits);
846 //////////////////////////////////////////////////////////////////////////////////////////////////
847 void AliTPCCompression::ReadTrailer(Int_t &WordsNumber,Int_t &PadNumber,Int_t &RowNumber,Int_t &SecNumber){
849 SecNumber=ReadWord(9);
850 RowNumber=ReadWord(10);
851 PadNumber=ReadWord(10);
852 WordsNumber=ReadWord(10);
855 //////////////////////////////////////////////////////////////////////////////////////////////////
856 ULong_t AliTPCCompression::GetDecodedWord(AliTPCHNode* root){
857 AliTPCHNode *node=root;
861 ULong_t bit=ReadWord(1);
863 node=node->GetRight();
865 node=node->GetLeft();
866 if (!(node->GetLeft())){
867 symbol=node->GetSymbol();
873 //////////////////////////////////////////////////////////////////////////////////////////////////
874 Int_t AliTPCCompression::DecompressData(Int_t NumTables,const char* fname,char* fDest){
875 cout<<" DECOMPRESSION:"<<endl;
876 cout<<"Source File "<<fname<<" Destination File "<<fDest<<endl;
877 f.open(fname,ios::binary|ios::in);
878 if(!f){cout<<"File doesn't exist\n";return -1;}
879 AliTPCHNode ** RootNode = new AliTPCHNode*[NumTables];
880 //Creation of the Huffman trees
881 CreateTrees(RootNode,NumTables);
882 //to go to the end of the file
884 //to get the file dimension in byte
886 fPos-=sizeof(ULong_t);
890 f.read((char*)(&fBuffer),sizeof(ULong_t));
898 ULong_t PacketNumber=ReadWord(sizeof(ULong_t)*8);
899 cout<<"Number of Packect: "<<PacketNumber<<endl;
900 AliTPCBuffer160 BufferFile(fDest,1);
902 ULong_t WordsRead=0; //number of read coded words
903 while(k<PacketNumber){
904 Int_t NumWords,PadNumber,RowNumber,SecNumber=0;
905 ReadTrailer(NumWords,PadNumber,RowNumber,SecNumber);
908 Int_t PreviousTime=-1;
910 Int_t NextTableType=0;
913 for(Int_t i=0;i<NumWords;i++){
914 ULong_t symbol=GetDecodedWord(RootNode[NextTableType]);
916 //Time reconstruction
917 if (NextTableType==1){
918 if (PreviousTime!=-1){
919 PreviousTime=symbol+PreviousTime+BunchLen;
921 else PreviousTime=symbol;
925 BufferFile.FillBuffer(symbol);
926 NextTable(symbol,NextTableType,BunchLen,Count);
927 if(NextTableType==0){
928 BufferFile.FillBuffer(Time);
929 BufferFile.FillBuffer(BunchLen+2);
933 BufferFile.WriteTrailer(NumWords,PadNumber,RowNumber,SecNumber);
935 cout<<"Number of decoded words:"<<WordsRead<<endl;
937 //The trees are deleted
938 for(Int_t j=0;j<NumTables;j++){
939 DeleteHuffmanTree(RootNode[j]);
945 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
947 Int_t AliTPCCompression::DecompressDataOptTables(Int_t NumTables,const char* fname,char* fDest){
949 cout<<" DECOMPRESSION:"<<endl;
950 cout<<"Source File "<<fname<<" Destination File "<<fDest<<endl;
952 AliTPCHNode ** RootNode = new AliTPCHNode*[NumTables];
953 //Creation of the Huffman trees
954 CreateTreesFromFile(RootNode,NumTables);
955 f.open(fname,ios::binary|ios::in);
956 if(!f){cout<<"File doesn't exist\n";return -1;}
957 //to go to the end of the file
959 //to get the file dimension in byte
961 fPos-=sizeof(ULong_t);
965 f.read((char*)(&fBuffer),sizeof(ULong_t));
973 ULong_t PacketNumber=ReadWord(sizeof(ULong_t)*8);
975 cout<<"Number of Packect: "<<PacketNumber<<endl;
977 AliTPCBuffer160 BufferFile(fDest,1);
979 ULong_t WordsRead=0; //number of read coded words
980 while(k<PacketNumber){
981 Int_t NumWords,PadNumber,RowNumber,SecNumber=0;
982 ReadTrailer(NumWords,PadNumber,RowNumber,SecNumber);
985 Int_t PreviousTime=-1;
987 Int_t NextTableType=0;
990 for(Int_t i=0;i<NumWords;i++){
991 ULong_t symbol=GetDecodedWord(RootNode[NextTableType]);
993 //Time reconstruction
994 if (NextTableType==1){
995 if (PreviousTime!=-1){
996 PreviousTime=symbol+PreviousTime+BunchLen;
998 else PreviousTime=symbol;
1002 BufferFile.FillBuffer(symbol);
1003 NextTable(symbol,NextTableType,BunchLen,Count);
1004 if(NextTableType==0){
1005 BufferFile.FillBuffer(Time);
1006 BufferFile.FillBuffer(BunchLen+2);
1010 BufferFile.WriteTrailer(NumWords,PadNumber,RowNumber,SecNumber);
1013 cout<<"Number of decoded words:"<<WordsRead<<endl;
1016 //The trees are deleted
1017 for(Int_t j=0;j<NumTables;j++){
1018 DeleteHuffmanTree(RootNode[j]);
1024 ///////////////////////////////////////////////////////////////////////////////////////////
1026 void AliTPCCompression::ReadAltroFormat(char* fileOut,char* fileIn){
1027 ofstream ftxt(fileOut);
1028 AliTPCBuffer160 Buff(fileIn,0);
1029 Int_t NumWords,PadNum,RowNum,SecNum=0;
1031 while(Buff.ReadTrailerBackward(NumWords,PadNum,RowNum,SecNum) !=-1 ){
1032 ftxt<<"W:"<<NumWords<<" P:"<<PadNum<<" R:"<<RowNum<<" S:"<<SecNum<<endl;
1034 for(Int_t j=0;j<(4-NumWords%4);j++){
1035 Value=Buff.GetNextBackWord();
1038 for(Int_t i=0;i<NumWords;i++){
1039 Value=Buff.GetNextBackWord();
1047 //////////////////////////////////////////////////////////////////////////////////////////