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