]>
Commit | Line | Data |
---|---|---|
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 | |
33 | ClassImp(AliTPCCompression) | |
34 | ////////////////////////////////////////////////////////////////////////////////////////////////// | |
35 | AliTPCCompression::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 | 48 | AliTPCCompression::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 | ////////////////////////////////////////////////////////////////////////////////////////////////// | |
62 | AliTPCCompression& 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 | 75 | void 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 | 128 | Int_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 | //////////////////////////////////////////////////////////////////////////////////////// | |
236 | Int_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 | 264 | Int_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 | 328 | Int_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 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
431 | Int_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 | |
469 | Int_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 | 525 | void 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 | ////////////////////////////////////////////////////////////////////////////////////////////////// | |
552 | void 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 | 562 | UInt_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 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
579 | Int_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 | 763 | void 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 | ////////////////////////////////////////////////////////////////////////////////////////////////// | |
827 | void 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 | ////////////////////////////////////////////////////////////////////////////////////////////////// | |
838 | void 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 | 847 | UInt_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 | 869 | UInt_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 | ////////////////////////////////////////////////////////////////////////////////////////////////// | |
899 | void 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 | 918 | UInt_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 | 942 | Int_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 | 1025 | Int_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 | 1112 | Int_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 | 1123 | void 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 | ////////////////////////////////////////////////////////////////////////////////////////// |