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