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 | ////////////////////////////////////////////////////////////////////////////////////////// |