]> git.uio.no Git - u/mrichter/AliRoot.git/blame - TPC/AliTPCCompression.cxx
Updated by J. Chudoba
[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 **************************************************************************/
15
16#include <TObjArray.h>
17#include "Riostream.h"
0f0615a3 18#include "TMath.h"
2e9f335b 19#include "AliTPCCompression.h"
20#include "AliTPCBuffer160.h"
21#include "AliTPCHuffman.h"
22
23ClassImp(AliTPCCompression)
24//////////////////////////////////////////////////////////////////////////////////////////////////
25AliTPCCompression::AliTPCCompression(){
26 fDimBuffer=sizeof(ULong_t)*8;
27 fFreeBitsBuffer=fDimBuffer;
28 fReadBits=0;
29 fPos=0;
30 fBuffer=0;
31 fVerbose=0;
32 fFillWords=0;
33 return;
34}
35//////////////////////////////////////////////////////////////////////////////////////////////////
36AliTPCCompression::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;
44 return;
45}
46//////////////////////////////////////////////////////////////////////////////////////////////////
47AliTPCCompression& 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;
55 return *this;
56}
57//////////////////////////////////////////////////////////////////////////////////////////////////
58void AliTPCCompression::NextTable(Int_t Val,Int_t &NextTableType,Int_t &BunchLen,Int_t &Count){
59 /*
60 Table index:
61 0==> Bunch length value
62 1==> Time Bin value
63 2==> 1-samples bunch
64 3==> Central samples
65 4==> Border samples
66 */
67 switch (NextTableType){
68 case 0:{
69 BunchLen=Val-2;
70 NextTableType=1;
71 break;
72 }//end case 0
73 case 1:{
74 if (BunchLen==1)NextTableType=2;
75 else{
76 NextTableType=4;
77 Count=1;
78 }
79 break;
80 }//end case 1
81 case 2:{
82 NextTableType=0;
83 break;
84 }//end case 2
85 case 3:{
86 Count++;
87 if (Count==(BunchLen-1)){
88 NextTableType=4;
89 }
90 break;
91 }//end case 3
92 case 4:{
93 if (Count==1){
94 if (BunchLen>2)
95 NextTableType=3;
96 else
97 Count++;
98 }
99 else
100 NextTableType=0;
101 break;
102 }//end case 4
103 }//end switch
104 return;
105}
106
107/////////////////////////////////////////////////////////////////////////////////////////////////////
108
109/////////////////////////////////////////////////////////////////////////////////////////////////////
110
111Int_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;
117 Int_t Value=0;
118 ULong_t Stat[5]={0,0,0,0,0};
119 Int_t EndFill=0;
120 Int_t End=1;
121 while(Buff.ReadTrailerBackward(NumWords,PadNum,RowNum,SecNum) !=-1 ){
122 if(End){
123 EndFill=Buff.GetFillWordsNum();
124 End=0;
125 }//endif
126 CountTrailer++;
127 if (NumWords%4){
128 fFillWords+=4-NumWords%4;
129 for(Int_t j=0;j<(4-NumWords%4);j++){
130 Value=Buff.GetNextBackWord();
131 }//end for
132 }//end if
133
134 Int_t Packet[1024];
135 Int_t TimePos[345];
136 Int_t Tp=0;
137 for(Int_t i=0;i<345;i++)TimePos[i]=0;
138 for(Int_t i=0;i<1024;i++)Packet[i]=0;
139
140 Int_t NextTableType=0;
141 Int_t BunchLen=0;
142 Int_t Count=0;
143 for(Int_t i=0;i<NumWords;i++){
144 Value=Buff.GetNextBackWord();
145 Packet[i]=Value;
146 if(NextTableType==1){
147 TimePos[Tp]=i;
148 Tp++;
149 }
150 NextTable(Value,NextTableType,BunchLen,Count);
151 }//end for
152 //computing the Time gap between two bunches
153 Int_t temp=0;
154 Tp--;
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;
159 temp=Packet[TimPos];
160 Packet[TimPos]=Packet[TimPos]-PreviousTime-BunchLen;
161 PreviousTime=temp;
162 }
163 NextTableType=0;
164 Count=0;
165 BunchLen=0;
166 for(Int_t i=0;i<NumWords;i++){
167 Value=Packet[i];
168 table[NextTableType]->SetFrequency(Value);
169 Stat[NextTableType]++;
170 NextTable(Value,NextTableType,BunchLen,Count);
171 CountWords++;
172 }//end for
173 }//end while
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;
178 //STATISTICS
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;
0f0615a3 191 ULong_t FileDimension=(ULong_t)TMath::Ceil(double((CountTrailer*4+CountWords+fFillWords+EndFill)*10/8));
2e9f335b 192 stat<<"Total file Size in bytes.."<<FileDimension<<endl;
0f0615a3 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;
2e9f335b 195 Percentage=(Double_t)CountTrailer*500/FileDimension;
196 stat<<"Trailer..................."<<CountTrailer*5<<" bytes "<<Percentage<<"%"<<endl;
197
198 Percentage=(Double_t)((Stat[0]+Stat[1]+Stat[2]+Stat[3]+Stat[4])) *125/FileDimension;
0f0615a3 199 stat<<"Data......................"<<(ULong_t)TMath::Ceil((Stat[0]+Stat[1]+Stat[2]+Stat[3]+Stat[4])*10/8)<<" bytes "<<Percentage<<"%"<<endl;
2e9f335b 200
201 Percentage=(Double_t)(Stat[0]*125)/FileDimension;
0f0615a3 202 stat<<"Bunch....................."<<(ULong_t)TMath::Ceil(Stat[0]*10/8)<<" bytes "<<Percentage<<"%"<<endl; //
2e9f335b 203 Percentage=(Double_t)(Stat[1]*125)/FileDimension;
0f0615a3 204 stat<<"Time......................"<<(ULong_t)TMath::Ceil(Stat[1]*10/8)<<" bytes "<<Percentage<<"%"<<endl; //
2e9f335b 205
206
207 Percentage=(Double_t)((Stat[2]+Stat[3]+Stat[4])) *125/FileDimension;
0f0615a3 208 stat<<"Amplitude values.........."<<(ULong_t)TMath::Ceil((Stat[2]+Stat[3]+Stat[4])*10/8)<<" bytes "<<Percentage<<"%"<<endl;
2e9f335b 209 Percentage=(Double_t)(Stat[2]*125)/FileDimension;
0f0615a3 210 stat<<" One Samples..............."<<(ULong_t)TMath::Ceil(Stat[2]*10/8)<<" bytes "<<Percentage<<"%"<<endl; //
2e9f335b 211 Percentage=(Double_t)(Stat[3]*125)/FileDimension;
0f0615a3 212 stat<<" Central Samples..........."<<(ULong_t)TMath::Ceil(Stat[3]*10/8)<<" bytes "<<Percentage<<"%"<<endl; //
2e9f335b 213 Percentage=(Double_t)(Stat[4]*125)/FileDimension;
0f0615a3 214 stat<<" Border Samples............"<<(ULong_t)TMath::Ceil(Stat[4]*10/8)<<" bytes "<<Percentage<<"%"<<endl; //
2e9f335b 215 stat.close();
216 return 0;
217}
218////////////////////////////////////////////////////////////////////////////////////////
219Int_t AliTPCCompression::StoreTables(AliTPCHTable* table[],const Int_t NumTable){
220 char filename[15];
221 ofstream fTable;
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));
236 } //end for
237 fTable.close();
238 }//end for
239 return 0;
240}
241////////////////////////////////////////////////////////////////////////////////////////
242Int_t AliTPCCompression::CreateTables(const char* fSource,const Int_t NumTables){
243 Int_t n=10;// 10 bits per symbol
244 /*
245 Table index:
246 0==> Bunch length values
247 1==> Time Bin values
248 2==> 1-samples bunch
249 3==> Central samples
250 4==> Border samples
251 */
252 AliTPCHTable ** table = new AliTPCHTable*[NumTables];
253 //The table is inizialized with the rigth number of rows
0f0615a3 254 for(Int_t i=0;i<NumTables;i++){table[i]=new AliTPCHTable((Int_t)(TMath::Power(2,n)));}
2e9f335b 255 //The frequencies are calculated and the tables are filled
256 if (fVerbose)
257 cout<<"Filling tables...\n";
258 //The get the frequencies
259 FillTables(fSource,table,NumTables);
260
261 //This part will be used in the table optimization phase
262 /*
263 for(Int_t i=0;i<NumTables;i++){
264 table[i]->CompleteTable(i);
265 }
266 */
267 if(fVerbose){
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;
273 }
274 stat.open("Statistics",ios::app);
275 stat<<endl;
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;
282 stat.close();
283
284 if (fVerbose)
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");
293 if (fVerbose)
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();
298 if (fVerbose==2){
299 cout<<"Number of elements inside the table:"<<table[i]->GetWordsNumber();
300 switch(i){
301 case 0:{
302 cout<<" (Bunch Length)"<<endl;
303 break;
304 }
305 case 1:{
306 cout<<" (Time Bin)"<<endl;
307 break;
308 }
309 case 2:{
310 cout<<" (1 Samples Bunch)"<<endl;
311 break;
312 }
313 case 3:{
314 cout<<" (Central Samples)"<<endl;
315 break;
316 }
317 case 4:{
318 cout<<" (Border Samples)"<<endl;
319 break;
320 }
321 }//end switch
322 table[i]->PrintTable();
323 }
324 }
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];
329 delete [] table;
330 return 0;
331}
332/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
333Int_t AliTPCCompression::RetrieveTables(AliTPCHTable* table[],Int_t NumTable){
334 if (fVerbose)
335 cout<<"Retrieving tables from files \n";
336 // ULong_t Code;
337 Double_t Code;
338 UChar_t CodeLen;
339 ifstream fTable;
340 char filename[15];
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));
347 if (fVerbose)
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);
356 }//end for
357 fTable.close();
358 }//end for
359 if (fVerbose)
360 cout<<"Trees generated \n";
361 //At this point the trees are been built
362 return 0;
363}
364////////////////////////////////////////////////////////////////////////////////////////
365/* COMPRESSION */
366////////////////////////////////////////////////////////////////////////////////////////
367
368void 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;
372 fBuffer=fBuffer|val;
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;
376 fBuffer=0;
377 }
378 }//end if
379 else{ //val has to be splitted in two buffers
380 fBuffer=fBuffer<<fFreeBitsBuffer;
381 ULong_t temp;
382 temp=val;
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;
389 fBuffer=val;
390 }//end else
391 return;
392}
393//////////////////////////////////////////////////////////////////////////////////////////////////
394void 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));
399 }//end if
400 return;
401}
402//////////////////////////////////////////////////////////////////////////////////////////////////
403ULong_t AliTPCCompression::Mirror(ULong_t val,UChar_t len){
404 ULong_t specular=0;
405 ULong_t Mask=0x1;
406 ULong_t bit;
407 for(Int_t i=0;i<len;i++){
408 bit=val&Mask;
409 bit=bit>>i;
410 specular=specular<<1;
411 specular=specular|bit;
412 Mask=Mask<<1;
413 }
414 return specular;
415}
416//////////////////////////////////////////////////////////////////////////////////////////////////
417Int_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));
433 } //end for
434 }//end for
435
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;
441 Int_t Value=0;
442 ULong_t NumPacket=0;
443 while(Buff.ReadTrailerBackward(NumWords,PadNum,RowNum,SecNum) !=-1 ){
444 NumPacket++;
445 if (NumWords%4){
446 for(Int_t j=0;j<(4-NumWords%4);j++){
447 Value=Buff.GetNextBackWord();
448 }//end for
449 }//end if
450
451 Int_t Packet[1024];
452 Int_t TimePos[345];
453 Int_t Tp=0;
454 for(Int_t i=0;i<345;i++)TimePos[i]=0;
455 for(Int_t i=0;i<1024;i++)Packet[i]=0;
456
457 Int_t NextTableType=0;
458 Int_t BunchLen=0;
459 Int_t Count=0;
460 for(Int_t i=0;i<NumWords;i++){
461 Value=Buff.GetNextBackWord();
462 Packet[i]=Value;
463 if(NextTableType==1){
464 TimePos[Tp]=i;
465 Tp++;
466 }
467 NextTable(Value,NextTableType,BunchLen,Count);
468 }//end for
469 //computing the Time gap between two bunches
470 Int_t temp=0;
471 Tp--;
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;
476 temp=Packet[TimPos];
477 Packet[TimPos]=Packet[TimPos]-PreviousTime-BunchLen;
478 PreviousTime=temp;
479 }//end for
480 NextTableType=0;
481 Count=0;
482 BunchLen=0;
483 Int_t TimeBin=0;
484 //All the words for one pad are compressed and stored in the compress file
485 for(Int_t i=0;i<NumWords;i++){
486 Value=Packet[i];
487 if(NextTableType==1)TimeBin=Value;
488 if(NextTableType>1){
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);
493 StoredWords++;
494 }//end if
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);
505 StoredWords+=2;
506 }
507 }//end for
508 //Trailer
509 StoreValue(NumWords,10);
510 StoreValue(PadNum,10);
511 StoreValue(RowNum,10);
512 StoreValue(SecNum,9);
513 StoreValue(1,1);
514 StoredWords+=4;
515 }//end while
516 StoreValue(NumPacket,32);
517 cout<<"Number of strored packet: "<<NumPacket<<endl;
518 StoreValue(1,1);
519 //The last buffen cannot be completely full
520 Flush();
521 cout<<"Number of stored words: "<<StoredWords<<endl;
522 f.close();
523 return 0;
524}
525
526/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
527Int_t AliTPCCompression::CompressDataOptTables(Int_t NumTable,const char* fSource,const char* fDest){
528 if (fVerbose){
529 cout<<" BackWord COMPRESSION "<<endl;
530 cout<<"compression of the file "<<fSource<<" Output File: "<<fDest<<endl;
531 }
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;
542 Int_t Value=0;
543 ULong_t NumPacket=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);
549 stat<<endl;
550 stat<<"-------------------COMPRESSION STATISTICS----------"<<endl;
551 Int_t End=1;
552 while(Buff.ReadTrailerBackward(NumWords,PadNum,RowNum,SecNum) !=-1 ){
553 if(End){
554 FillWords=Buff.GetFillWordsNum();
555 End=0;
556 }//endif
557
558 NumPacket++;
559 if (NumWords%4){
560 FillWords+=4-NumWords%4;
561 for(Int_t j=0;j<(4-NumWords%4);j++){
562 Value=Buff.GetNextBackWord();
563 }//end for
564 }//end if
565
566 Int_t Packet[1024];
567 Int_t TimePos[345];
568 Int_t Tp=0;
569 for(Int_t i=0;i<345;i++)TimePos[i]=0;
570 for(Int_t i=0;i<1024;i++)Packet[i]=0;
571
572 Int_t NextTableType=0;
573 Int_t BunchLen=0;
574 Int_t Count=0;
575 for(Int_t i=0;i<NumWords;i++){
576 Value=Buff.GetNextBackWord();
577 Packet[i]=Value;
578 if(NextTableType==1){
579 TimePos[Tp]=i;
580 Tp++;
581 }
582 NextTable(Value,NextTableType,BunchLen,Count);
583 }//end for
584 //computing the Time gap between two bunches
585 Int_t temp=0;
586 Tp--;
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;
591 temp=Packet[TimPos];
592 Packet[TimPos]=Packet[TimPos]-PreviousTime-BunchLen;
593 PreviousTime=temp;
594 }//end for
595
596 NextTableType=0;
597 Count=0;
598 BunchLen=0;
599 Int_t TimeBin=0;
600 for(Int_t i=0;i<NumWords;i++){
601 Value=Packet[i];
602 if(NextTableType==1)TimeBin=Value;
603 if(NextTableType>1){
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);
610 StoredWords++;
611 }//end if
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
617 Stat[1]+=len;
618 NumElem[1]++;
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]++;
626 StoredWords+=2;
627 }
628 }//end for
629 //Trailer
630 StoreValue(NumWords,10);
631 StoreValue(PadNum,10);
632 StoreValue(RowNum,10);
633 StoreValue(SecNum,9);
634 StoreValue(1,1);
635 StoredWords+=4;
636 TrailerNumber++;
637 }//end while
638 StoreValue(NumPacket,32);
639 if(fVerbose)
640 cout<<"Number of strored packet: "<<NumPacket<<endl;
641 StoreValue(1,1);
642 //The last buffen cannot be completely full
643 Flush();
644 if(fVerbose)
645 cout<<"Number of stored words: "<<StoredWords<<endl;
646 f.close();
647 //Tables are deleted
648 for(Int_t i=0;i<NumTable;i++){
649 delete table[i];
650 }//end for
651 delete [] table;
0f0615a3 652 Double_t dimension=(ULong_t)TMath::Ceil((Stat[0]+Stat[1]+Stat[2]+Stat[3]+Stat[4])/8)+TrailerNumber*5;
2e9f335b 653 stat<<"Trailer Dimension in bytes......"<<TrailerNumber*5<<endl;
0f0615a3 654 stat<<"Data Dimension in bytes........."<<(ULong_t)TMath::Ceil((Stat[0]+Stat[1]+Stat[2]+Stat[3]+Stat[4])/8)<<endl;
2e9f335b 655 stat<<"Compressed file dimension......."<<(ULong_t)dimension<<endl;
656 /*
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;
664 */
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;
667
668 Double_t ratio=(dimension/FillWords)*100;
669 stat<<"Compression ratio (Compressed/Uncompressed)..."<<ratio<<"%"<<endl;
670 stat<<endl;
0f0615a3 671 stat<<"Bunch length size in bytes......"<<(ULong_t)TMath::Ceil(Stat[0]/8)<<" Comppression.."<<(Stat[0]/NumElem[0])*10<<"%"<<endl;
2e9f335b 672
0f0615a3 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.."<<
2e9f335b 675 ((Stat[2]+Stat[3]+Stat[4])/(NumElem[2]+NumElem[3]+NumElem[4]))*10<<"%"<<endl;
0f0615a3 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;
2e9f335b 679 stat<<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;
686 stat.close();
687 return 0;
688}
689
690////////////////////////////////////////////////////////////////////////////////////////
691
692////////////////////////////////////////////////////////////////////////////////////////
693/* DECOMPRESSION */
694////////////////////////////////////////////////////////////////////////////////////////
695void 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
698 if(fVerbose)
699 cout<<"Creating the Huffman trees \n";
700 AliTPCHNode *node=0;
701 // ULong_t Code;
702 Double_t Code;
703 UChar_t CodeLen;
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));
709 if (fVerbose)
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));
716 node=RootNode[k];
717 for(Int_t j=1;j<=CodeLen;j++){
718 ULong_t bit,val=0;
0f0615a3 719 val=(ULong_t)TMath::Power(2,CodeLen-j);
2e9f335b 720 bit=(ULong_t)Code&val;
721 AliTPCHNode *temp=node;
722 if(bit){
723 node=node->GetRight();
724 if(!node){
725 node=new AliTPCHNode();
726 temp->SetRight(node);
727 }//end if
728 }//end if
729 else{
730 node=node->GetLeft();
731 if(!node){
732 node=new AliTPCHNode();
733 temp->SetLeft(node);
734 }//end if
735 }//end else
736 }//end for
737 if(CodeLen){
738 node->SetSymbol(i);
739 node->SetFrequency(CodeLen);
740 }//end if
741 //cout<<node->GetSymbol()<<" "<<(Int_t)node->GetFrequency()<<endl;
742 }//end for
743 }//end for
744 if (fVerbose)
745 cout<<"Trees generated \n";
746 //At this point the trees are been built
747}
748//////////////////////////////////////////////////////////////////////////////////////////////////
749void AliTPCCompression::CreateTreesFromFile(AliTPCHNode *RootNode[],const Int_t NumTables){
750 if(fVerbose)
751 cout<<"Creating the Huffman trees \n";
752 AliTPCHNode *node=0;
753 // ULong_t Code;
754 Double_t Code;
755 UChar_t CodeLen;
756 ifstream fTable;
757 char filename[15];
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));
766 if (fVerbose)
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));
773 node=RootNode[k];
774 for(Int_t j=1;j<=CodeLen;j++){
775 ULong_t bit,val=0;
0f0615a3 776 val=(ULong_t)TMath::Power(2,CodeLen-j);
2e9f335b 777 bit=(ULong_t)Code&val;
778 AliTPCHNode *temp=node;
779 if(bit){
780 node=node->GetRight();
781 if(!node){
782 node=new AliTPCHNode();
783 temp->SetRight(node);
784 }//end if
785 }//end if
786 else{
787 node=node->GetLeft();
788 if(!node){
789 node=new AliTPCHNode();
790 temp->SetLeft(node);
791 }//end if
792 }//end else
793 }//end for
794 if(CodeLen){
795 node->SetSymbol(i);
796 node->SetFrequency(CodeLen);
797 }//end if
798 }//end for
799 fTable.close();
800 }//end for
801 if (fVerbose)
802 cout<<"Trees generated \n";
803 //At this point the trees are been built
804}
805//////////////////////////////////////////////////////////////////////////////////////////////////
806void 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
809 if (node){
810 DeleteHuffmanTree(node->GetLeft());
811 DeleteHuffmanTree(node->GetRight());
812 // cout<<node->GetSymbol()<<" "<<(Int_t)node->GetFrequency()<<endl;
813 delete node;
814 }
815}
816//////////////////////////////////////////////////////////////////////////////////////////////////
817void AliTPCCompression::VisitHuffmanTree(AliTPCHNode* node){
818 //This function realizes an in order visit of a binary tree
819 if (node){
820 cout<<node->GetSymbol()<<" "<<node->GetFrequency()<<endl;
821 VisitHuffmanTree(node->GetLeft());
822 VisitHuffmanTree(node->GetRight());
823 }
824}
825//////////////////////////////////////////////////////////////////////////////////////////////////
826ULong_t AliTPCCompression::ReadWord(Int_t NumberOfBit){
827 ULong_t Result=0;
828 ULong_t bit=0;
829 for (Int_t i=0;i<NumberOfBit;i++){
830 if (fReadBits==32){
831 fPos-=sizeof(ULong_t);
832 f.seekg(fPos);
833 f.read((char*)(&fBuffer),sizeof(ULong_t));
834 fReadBits=0;
835 }//end if
836 ULong_t mask=0;
0f0615a3 837 mask=(ULong_t)TMath::Power(2,fReadBits);
2e9f335b 838 bit=fBuffer&mask;
839 bit=bit>>fReadBits;
840 fReadBits++;
841 bit=bit<<i;
842 Result=Result|bit;
843 }//end for
844 return Result;
845}
846//////////////////////////////////////////////////////////////////////////////////////////////////
847void AliTPCCompression::ReadTrailer(Int_t &WordsNumber,Int_t &PadNumber,Int_t &RowNumber,Int_t &SecNumber){
848 ReadWord(1);
849 SecNumber=ReadWord(9);
850 RowNumber=ReadWord(10);
851 PadNumber=ReadWord(10);
852 WordsNumber=ReadWord(10);
853 return;
854}
855//////////////////////////////////////////////////////////////////////////////////////////////////
856ULong_t AliTPCCompression::GetDecodedWord(AliTPCHNode* root){
857 AliTPCHNode *node=root;
858 ULong_t symbol=0;
859 Bool_t decoded=0;
860 while(!decoded){
861 ULong_t bit=ReadWord(1);
862 if(bit)
863 node=node->GetRight();
864 else
865 node=node->GetLeft();
866 if (!(node->GetLeft())){
867 symbol=node->GetSymbol();
868 decoded=1;
869 }
870 }//end while
871 return symbol;
872}
873//////////////////////////////////////////////////////////////////////////////////////////////////
874Int_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
883 f.seekg(0,ios::end);
884 //to get the file dimension in byte
885 fPos=f.tellg();
886 fPos-=sizeof(ULong_t);
887 f.seekg(fPos);
888 fReadBits=0;
889 fBuffer=0;
890 f.read((char*)(&fBuffer),sizeof(ULong_t));
891 Int_t bit=0;
892 ULong_t Mask=0x1;
893 while(!bit){
894 bit=fBuffer&Mask;
895 Mask=Mask<<1;
896 fReadBits++;
897 }
898 ULong_t PacketNumber=ReadWord(sizeof(ULong_t)*8);
899 cout<<"Number of Packect: "<<PacketNumber<<endl;
900 AliTPCBuffer160 BufferFile(fDest,1);
901 ULong_t k=0;
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);
906 k++;
907 WordsRead+=4;
908 Int_t PreviousTime=-1;
909 Int_t Time=0;
910 Int_t NextTableType=0;
911 Int_t BunchLen=0;
912 Int_t Count=0;
913 for(Int_t i=0;i<NumWords;i++){
914 ULong_t symbol=GetDecodedWord(RootNode[NextTableType]);
915 WordsRead++;
916 //Time reconstruction
917 if (NextTableType==1){
918 if (PreviousTime!=-1){
919 PreviousTime=symbol+PreviousTime+BunchLen;
920 }
921 else PreviousTime=symbol;
922 Time=PreviousTime;
923 }
924 if(NextTableType>1)
925 BufferFile.FillBuffer(symbol);
926 NextTable(symbol,NextTableType,BunchLen,Count);
927 if(NextTableType==0){
928 BufferFile.FillBuffer(Time);
929 BufferFile.FillBuffer(BunchLen+2);
930 BunchLen=0;
931 }
932 }//end for
933 BufferFile.WriteTrailer(NumWords,PadNumber,RowNumber,SecNumber);
934 }//end while
935 cout<<"Number of decoded words:"<<WordsRead<<endl;
936 f.close();
937 //The trees are deleted
938 for(Int_t j=0;j<NumTables;j++){
939 DeleteHuffmanTree(RootNode[j]);
940 }//end for
941 delete [] RootNode;
942 return 0;
943}
944
945//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
946
947Int_t AliTPCCompression::DecompressDataOptTables(Int_t NumTables,const char* fname,char* fDest){
948 if(fVerbose){
949 cout<<" DECOMPRESSION:"<<endl;
950 cout<<"Source File "<<fname<<" Destination File "<<fDest<<endl;
951 }
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
958 f.seekg(0,ios::end);
959 //to get the file dimension in byte
960 fPos=f.tellg();
961 fPos-=sizeof(ULong_t);
962 f.seekg(fPos);
963 fReadBits=0;
964 fBuffer=0;
965 f.read((char*)(&fBuffer),sizeof(ULong_t));
966 Int_t bit=0;
967 ULong_t Mask=0x1;
968 while(!bit){
969 bit=fBuffer&Mask;
970 Mask=Mask<<1;
971 fReadBits++;
972 }
973 ULong_t PacketNumber=ReadWord(sizeof(ULong_t)*8);
974 if(fVerbose){
975 cout<<"Number of Packect: "<<PacketNumber<<endl;
976 }
977 AliTPCBuffer160 BufferFile(fDest,1);
978 ULong_t k=0;
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);
983 k++;
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++){
991 ULong_t symbol=GetDecodedWord(RootNode[NextTableType]);
992 WordsRead++;
993 //Time reconstruction
994 if (NextTableType==1){
995 if (PreviousTime!=-1){
996 PreviousTime=symbol+PreviousTime+BunchLen;
997 }
998 else PreviousTime=symbol;
999 Time=PreviousTime;
1000 }
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;
1008 }
1009 }//end for
1010 BufferFile.WriteTrailer(NumWords,PadNumber,RowNumber,SecNumber);
1011 }//end while
1012 if(fVerbose){
1013 cout<<"Number of decoded words:"<<WordsRead<<endl;
1014 }
1015 f.close();
1016 //The trees are deleted
1017 for(Int_t j=0;j<NumTables;j++){
1018 DeleteHuffmanTree(RootNode[j]);
1019 }//end for
1020 delete [] RootNode;
1021 return 0;
1022}
1023
1024///////////////////////////////////////////////////////////////////////////////////////////
1025
1026void AliTPCCompression::ReadAltroFormat(char* fileOut,char* fileIn){
1027 ofstream ftxt(fileOut);
1028 AliTPCBuffer160 Buff(fileIn,0);
1029 Int_t NumWords,PadNum,RowNum,SecNum=0;
1030 Int_t Value=0;
1031 while(Buff.ReadTrailerBackward(NumWords,PadNum,RowNum,SecNum) !=-1 ){
1032 ftxt<<"W:"<<NumWords<<" P:"<<PadNum<<" R:"<<RowNum<<" S:"<<SecNum<<endl;
1033 if (NumWords%4){
1034 for(Int_t j=0;j<(4-NumWords%4);j++){
1035 Value=Buff.GetNextBackWord();
1036 }//end for
1037 }//end if
1038 for(Int_t i=0;i<NumWords;i++){
1039 Value=Buff.GetNextBackWord();
1040 ftxt<<Value<<endl;
1041 }//end for
1042 }//end while
1043 ftxt.close();
1044 return;
1045}
1046
1047//////////////////////////////////////////////////////////////////////////////////////////