Using TMath::Abs instead of fabs
[u/mrichter/AliRoot.git] / HLT / misc / AliL3DataHandler.cxx
1 //$Id$
2
3 // Author: Anders Vestbo <mailto:vestbo@fi.uib.no>
4 //*-- Copyright &copy ASV
5
6 #include "AliL3StandardIncludes.h"
7
8 #include "AliL3DataHandler.h"
9 #include "AliL3Logging.h"
10 #include "AliL3TransBit.h"
11 #include "AliL3Transform.h"
12
13 #if GCCVERSION == 3
14 using namespace std;
15 #endif
16
17 //_____________________________________________________________
18 // AliL3DataHandler
19 //
20 // HLT Binary file handler.
21 //
22 // This class have more or less the same functionality as AliL3MemHandler,
23 // except that it handles 8 bit ADC-values. Reading and writing is done in the same way
24 // as illustrated in example 1) and 2) in AliL3MemHandler.
25 //
26 // For converting 10 bit data files to 8 bit data files, do:
27 //
28 // AliL3MemHandler *file = new AliL3DataHandler();
29 // file->Init(slice,patch);
30 // file->SetBinaryInput(inputfile);    //10 bit data file
31 // file->SetBinaryOutput(outputfile);  //8 bit data file
32 // file->Convert10to8Bit();
33 // file->CloseBinaryInput();
34 // file->CloseBinaryOutput();
35 // delete file;
36 //
37 // Compress data format
38 // --------------------
39 //
40 // The data is RLE encoded, using _8_bit representation of the ADC-values.
41 // Conversion is done in the class AliL3TransBit.
42 //
43 // In the beginning of every row, the row number if written and the number of pads
44 // containing data on that row. For every pad with data the pad number is written,
45 // and then comes the ADC-values on that pad. When a serie of zeros occure, a zero
46 // is written followed by the number of zeros. If the number of zeros is more than
47 // 255 (8 bit), another 8 bit word is written for the remaining. At the end of one 
48 // pad, 2 zeros are written. Example:
49 //
50 // ROW NPADSWITHDATA PAD 0 NZEROS ADC ADC ADC ADC 0 NZEROS ADC ADC 0 0
51 //
52 // Everything is written using 8 bit;
53 // (ROW < 176, PAD < 200, ADC < 255, if(NZEROS > 255) write 2 words;)
54
55 ClassImp(AliL3DataHandler)
56   
57 AliL3DataHandler::AliL3DataHandler()
58 {
59   fBitTransformer = 0;
60   LOG(AliL3Log::kInformational,"AliL3DataHandler::AliL3DataHandler","Data format")
61     <<"8 bit data handler initialized"<<ENDLOG;
62 }
63
64 AliL3DataHandler::~AliL3DataHandler()
65 {
66   if(fBitTransformer)
67     delete fBitTransformer;
68 }
69
70 void AliL3DataHandler::Convert10to8Bit()
71 {
72   //Convert from 10 bit data in inputfile, to 8 bit data written to outputfile.
73   
74   if(!fInBinary)
75     {
76       LOG(AliL3Log::kError,"AliL3DataHandler::Convert10to8Bit","File")
77         <<AliL3Log::kHex<<"Pointer to input file : "<<(Int_t)fInBinary<<ENDLOG;
78       return;
79     }
80   if(!fOutBinary)
81     {
82       LOG(AliL3Log::kError,"AliL3DataHandler::Convert10to8Bit","File")
83         <<AliL3Log::kHex<<"Pointer to output file : "<<(Int_t)fOutBinary<<ENDLOG;
84       return;
85     }
86   
87   
88   //Initialize the bit transformation class:
89   fBitTransformer = new AliL3TransBit_v1();
90   Int_t b0=10;  // original number of bits
91   Int_t b1=8;   // compressed
92   fBitTransformer->SetBits(b0,b1);
93   fBitTransformer->FindOptimumX0();
94   fBitTransformer->Update();
95   
96   AliL3MemHandler *memory = new AliL3MemHandler();
97   memory->Init(fSlice,fPatch);
98   memory->SetBinaryInput(fInBinary);
99   UInt_t nrow;
100   AliL3DigitRowData *data = (AliL3DigitRowData*)memory->CompBinary2Memory(nrow);
101   
102   Memory2CompBinary(nrow,data);
103   
104   delete memory;
105 }
106
107 Bool_t AliL3DataHandler::Memory2CompBinary(UInt_t nrow,AliL3DigitRowData *data)
108 {
109   //Compress data by RLE, and write to a binary file.
110   
111   UInt_t size = GetCompMemorySize(nrow,data);
112   Byte_t *comp = Allocate(size);
113   Memory2CompMemory(nrow,data,comp);
114   if(!CompMemory2CompBinary(nrow,comp,size))
115     {
116       LOG(AliL3Log::kError,"AliL3DataHandler::Memory2CompBinary","File")
117         <<"Error writing to file "<<ENDLOG;
118       return 0;
119     }
120   Free();
121   return kTRUE;
122 }
123
124 AliL3DigitRowData *AliL3DataHandler::CompBinary2Memory(UInt_t &nrow)
125 {
126   //Read RLE compressed binary file, unpack it and return pointer to it.
127   
128   AliL3MemHandler *memory = new AliL3MemHandler();
129   memory->SetBinaryInput(fInBinary);
130   Byte_t *comp = memory->Allocate();
131     
132   if(!CompBinary2CompMemory(nrow,comp))
133     {
134       LOG(AliL3Log::kError,"AliL3DataHandler::CompBinary2Memory","File")
135         <<"Error reading from file "<<ENDLOG;
136       return 0;
137     }
138
139   UInt_t size = GetMemorySize(nrow,comp);
140   AliL3DigitRowData *data = (AliL3DigitRowData*)Allocate(size);
141   CompMemory2Memory(nrow,data,comp);
142   delete memory;
143   return data;
144 }
145
146 void AliL3DataHandler::Write(Byte_t *comp,UInt_t &index,UShort_t value)
147 {
148   //Write one value (=1 byte) to array comp.
149
150   if(value > 255)
151     {
152       LOG(AliL3Log::kFatal,"AliL3DataHandler::Write","Bitnumbers")
153         <<"Value too big for storing in 1 byte, something is wrong: "<<value<<" "<<index<<ENDLOG;
154     }
155   comp[index] = (Byte_t)value;
156   index++;
157 }
158
159 Short_t AliL3DataHandler::Read(Byte_t *comp,UInt_t &index)
160 {
161   //Read one value (=1 byte) from array comp
162
163   Short_t value = (Short_t)comp[index];
164   index++;
165   return value;
166 }
167
168 Short_t AliL3DataHandler::Test(Byte_t *comp,UInt_t index)
169 {
170   //Check the value (=1 byte) in array comp, but not read.
171
172   Short_t value = (Short_t)comp[index];
173   return value;
174 }
175
176 Bool_t AliL3DataHandler::Memory2CompMemory(UInt_t nrow,AliL3DigitRowData *data,Byte_t *comp)
177 {
178   //Perform RLE.
179   
180   if(!data)
181     {
182       LOG(AliL3Log::kError,"AliL3DataHandler::Memory2CompMemory","Data")
183         <<AliL3Log::kHex<<" Pointer to data = "<<(Int_t)data<<ENDLOG;
184       return 0;  
185     }
186   if(!comp)
187     {
188       LOG(AliL3Log::kError,"AliL3DataHandler::Memory2CompMemory","Data")
189         <<AliL3Log::kHex<<" Pointer to compressed data = "<<(Int_t)comp<<ENDLOG;
190       return 0;  
191     }
192
193   AliL3DigitRowData *rowPt = data;
194   
195   UInt_t index = 0;
196   Int_t npads[200];      
197   
198   for(UInt_t i=0; i<nrow; i++)
199     {
200       //Write the row number:
201       UShort_t value = rowPt->fRow;
202       Write(comp,index,value);
203       
204       UShort_t number_of_pads=0;
205       UShort_t max_pad = 0;
206       
207       for(Int_t j=0; j<200; j++)
208         npads[j]=0;
209       for(UInt_t dig=0; dig<rowPt->fNDigit; dig++)
210         {
211           if(rowPt->fDigitData[dig].fPad < 200)
212             npads[rowPt->fDigitData[dig].fPad]++;
213         }
214       for(Int_t j=0; j<200; j++)
215         {
216           if(npads[j])
217             {
218               number_of_pads++;
219               max_pad = j;
220             }
221         }
222       
223       //Write the number of pads on this row:
224       Write(comp,index,number_of_pads);
225       UInt_t digit=0;
226       
227       for(UShort_t pad=0; pad <= max_pad; pad++)
228         {
229           
230           if(digit >= rowPt->fNDigit || rowPt->fDigitData[digit].fPad !=  pad)
231             continue;
232         
233           //Write the current pad:
234           Write(comp,index,pad);
235           
236           if(digit < rowPt->fNDigit && rowPt->fDigitData[digit].fPad == pad)
237             {
238               if(rowPt->fDigitData[digit].fTime > 0)
239                 {
240                   //If first time!=0, write the number of following zeros, 
241                   //and then the first timebin:
242                   Write(comp,index,0);
243                   
244                   //Check if we have to use more than 1 byte to write the zeros:
245                   Int_t number_of_zero_intervals=0;
246                   if(rowPt->fDigitData[digit].fTime >= 255)
247                     {
248                       number_of_zero_intervals++;
249                       Write(comp,index,255);
250                       if(rowPt->fDigitData[digit].fTime >= 2*255)
251                         {
252                           cerr<<"AliL3DataHandler::Memory2CompMemory : Should not happen "<<(Int_t)rowPt->fDigitData[digit].fTime<<endl;
253                           Write(comp,index,255);
254                           number_of_zero_intervals++;
255                         }
256                     }
257                   Write(comp,index,(rowPt->fDigitData[digit].fTime - number_of_zero_intervals*255));
258                 }
259             }
260           
261           while(digit < rowPt->fNDigit && rowPt->fDigitData[digit].fPad == pad)
262             {
263               UShort_t charge = rowPt->fDigitData[digit].fCharge;
264               
265               if(fBitTransformer)
266                 charge = fBitTransformer->Get0to1(charge); //Transform 10 to 8 bit.
267               
268               //Check for saturation:
269               if(charge>255)
270                 {
271                   LOG(AliL3Log::kWarning,"AliL3DataHandler::Memory2CompMemory","Digit")
272                     <<"ADC-value saturated : "<<charge<<ENDLOG;
273                   charge=255;
274                 }
275               
276               //Write the charge:
277               Write(comp,index,charge);
278               
279               //Check if the next digit is zero:
280               if(digit+1 < rowPt->fNDigit && rowPt->fDigitData[digit+1].fPad == pad)
281                 {
282                   if(rowPt->fDigitData[digit].fTime + 1 != rowPt->fDigitData[digit+1].fTime)
283                     {
284                       Write(comp,index,0);
285                       UShort_t nzero = rowPt->fDigitData[digit+1].fTime - (rowPt->fDigitData[digit].fTime + 1);
286                       
287                       //Check if we have to use more than one byte to write the zeros:
288                       Int_t number_of_zero_intervals=0;
289                       if(nzero >= 255)
290                         {
291                           number_of_zero_intervals++;
292                           Write(comp,index,255);
293                           if(nzero >= 2*255)
294                             {
295                               cerr<<"AliL3DataHandler::Memory2CompMemory : Should not happen "<<(Int_t)rowPt->fDigitData[digit].fTime<<endl;
296                               Write(comp,index,255);
297                               number_of_zero_intervals++;
298                             }
299                         }
300                       Write(comp,index,(nzero - number_of_zero_intervals*255));
301                     }  
302                 }
303               digit++;
304             }
305           
306           //This is the end of the pad, state it with 2 zeros:
307           Write(comp,index,0);
308           Write(comp,index,0);
309         }
310       
311       UpdateRowPointer(rowPt);
312       
313     }
314   
315   return index * sizeof(Byte_t);
316     
317 }
318
319 UInt_t AliL3DataHandler::GetCompMemorySize(UInt_t nrow,AliL3DigitRowData *data)
320 {
321   //Calculate the size (in bytes) of RLE data.
322   
323   if(!data)
324     {
325       LOG(AliL3Log::kError,"AliL3DataHandler::GetCompMemorySize","Data")
326         <<AliL3Log::kHex<<" Data pointer = "<<(Int_t)data<<ENDLOG;
327       return 0;
328     }
329   
330   AliL3DigitRowData *rowPt = data;
331   
332   UInt_t index = 0;
333   Int_t npads[200];
334   
335   for(UInt_t i=0;i<nrow;i++)
336     {
337       //Write the row number:
338       index++;
339       
340       UShort_t max_pad=0; 
341       UShort_t number_of_pads = 0;
342       
343       for(Int_t j=0; j<200; j++) 
344         npads[j]=0;
345       
346       for(UInt_t dig=0; dig<rowPt->fNDigit; dig++)
347         {
348           if(rowPt->fDigitData[dig].fPad <200)
349             npads[rowPt->fDigitData[dig].fPad]++;
350         }
351       for(Int_t j=0; j<200; j++)
352         { 
353           if(npads[j])
354             {
355               number_of_pads++;
356               max_pad = j;
357             }
358         }
359       
360       //Write the number of pads on this row:
361       index++;
362       
363       UInt_t digit=0;
364       for(UShort_t pad=0; pad <= max_pad; pad++)
365         {
366           if(digit>=rowPt->fNDigit || rowPt->fDigitData[digit].fPad !=  pad)
367             continue;
368           
369           //Write the current pad:
370           index++;
371           
372           
373           if(digit<rowPt->fNDigit && rowPt->fDigitData[digit].fPad == pad)
374             {
375               if(rowPt->fDigitData[digit].fTime > 0)
376                 {
377                   //If first time!=0, write the number of following zeros, 
378                   //and then the first timebin:
379                   
380                   index++;
381                   index++;
382                   
383                   //Check if we have to use more than 1 byte to write the zeros:
384                   if(rowPt->fDigitData[digit].fTime >= 255)
385                     index++;
386                   if(rowPt->fDigitData[digit].fTime >= 2*255)
387                     index++;
388                 }
389             }
390           
391           while(digit < rowPt->fNDigit && rowPt->fDigitData[digit].fPad == pad)
392             {
393               //Write the charge:
394               index++;
395               
396               //Check if the next digit is zero:
397               if(digit+1 < rowPt->fNDigit && rowPt->fDigitData[digit+1].fPad == pad)
398                 {
399                   if(rowPt->fDigitData[digit].fTime +1 != rowPt->fDigitData[digit+1].fTime)
400                     {
401                       index++;
402                       index++;
403                       
404                       //Check if we have to use more than 1 byte to write the zeros:
405                       UInt_t nzeros = rowPt->fDigitData[digit+1].fTime - rowPt->fDigitData[digit].fTime + 1;
406                       if(nzeros >= 255)
407                         index++;
408                       if(nzeros >= 2*255)
409                         index++;
410                     }  
411                 }
412               digit++;
413             }
414           
415           //Mark the end of the pad with 2 zeros:
416           index++;
417           index++;
418         }
419       
420       UpdateRowPointer(rowPt);
421     }
422   
423   return index * sizeof(Byte_t);
424   
425 }
426
427 UInt_t AliL3DataHandler::CompMemory2Memory(UInt_t nrow,AliL3DigitRowData *data,Byte_t *comp)
428 {
429   //Uncompress RLE data.
430   
431   if(!data)
432     {
433       LOG(AliL3Log::kError,"AliL3DataHandler::CompMemory2Memory","Array")
434         <<AliL3Log::kHex<<"Pointer to data: "<<(Int_t)data<<ENDLOG;
435       return 0;
436     }
437   if(!comp)
438     {
439       LOG(AliL3Log::kError,"AliL3DataHandler::CompMemory2Memory","Array")
440         <<AliL3Log::kHex<<"Pointer to compressed data: "<<(Int_t)data<<ENDLOG;
441       return 0;
442     }
443   
444   Int_t outsize=0;
445   
446   AliL3DigitRowData *rowPt = data;
447   UInt_t index=0;
448
449   UShort_t pad,time,charge;
450   for(UInt_t i=0; i<nrow; i++)
451     {
452       UInt_t ndigit=0;
453       
454       //Read the row:
455       rowPt->fRow = Read(comp,index);
456
457       //Read the number of pads:
458       UShort_t npads = Read(comp,index);
459       
460       for(UShort_t p=0; p<npads; p++)
461         {
462           //Read the current pad:
463           pad = Read(comp,index);
464           
465           time = 0;
466           
467           //Check for zeros:
468           if(Test(comp,index) == 0) //Zeros
469             {
470               //Read the first zero
471               Read(comp,index);
472               
473                 
474               if(Test(comp,index) == 0)//end of pad.
475                 {
476                   time = Read(comp,index); 
477                   continue;
478                 }
479               if( (time = Read(comp,index)) == 255 )
480                 if( (time += Read(comp,index)) == 2*255)
481                   time += Read(comp,index);
482             }
483
484           while(1)
485             {
486               while( (charge = Read(comp,index)) != 0)
487                 {
488                   if(time >= AliL3Transform::GetNTimeBins())
489                     cerr<<"AliL3DataHandler::CompMemory2Memory : Time out of range "<<time<<endl;
490                   rowPt->fDigitData[ndigit].fPad = pad;
491                   rowPt->fDigitData[ndigit].fTime = time;
492                   rowPt->fDigitData[ndigit].fCharge = charge;
493                   ndigit++;
494                   if(Test(comp,index) != 0)
495                     time++;
496                 }
497               if(Test(comp,index) == 0)
498                 {
499                   Read(comp,index); //end of pad
500                   break;
501                 }
502               UShort_t time_shift;
503               if( (time_shift = Read(comp,index)) == 255)
504                 if( (time_shift += Read(comp,index)) == 2*255)
505                   time_shift += Read(comp,index);
506               time += time_shift;
507               
508             }
509         }
510       rowPt->fNDigit = ndigit;
511       UpdateRowPointer(rowPt);
512       outsize += sizeof(AliL3DigitData)*ndigit + sizeof(AliL3DigitRowData);
513     }
514   
515   return outsize;
516 }
517
518 UInt_t AliL3DataHandler::GetMemorySize(UInt_t nrow,Byte_t *comp)
519 {
520   //Calculate size (in bytes) of unpacked data.
521
522   UInt_t index=0;
523   Int_t outsize=0;
524   
525   for(UInt_t i=0; i<nrow; i++)
526     {
527       UInt_t ndigit=0;//Digits on this row.
528
529       //Row number:
530       Read(comp,index);
531       
532       UShort_t npad = Read(comp,index);
533       
534       for(UShort_t pad=0; pad<npad; pad++)
535         {
536           //Read the pad number:
537           Read(comp,index);
538           
539           //Check for zeros:
540           if(Test(comp,index)==0) //Zeros are coming
541             {
542               Read(comp,index);
543               if(Test(comp,index) == 0) 
544                 {
545                   Read(comp,index); //This was the end of pad.
546                   continue; 
547                 }
548               if(Read(comp,index) == 255) //There can be up to 3 bytes with zero coding.
549                 if(Read(comp,index) == 255)
550                   Read(comp,index);
551             }
552           
553           while(1)
554             {
555               while(Read(comp,index) != 0) ndigit++;
556               
557               if(Test(comp,index) == 0)
558                 {
559                   Read(comp,index); //2 zeros = end of pad.
560                   break;
561                 }
562               if(Read(comp,index) == 255) //There can be up to 3 bytes with zero coding.
563                 if(Read(comp,index) == 255)
564                   Read(comp,index);
565               
566             }
567           
568         }
569       Int_t size = sizeof(AliL3DigitData)*ndigit + sizeof(AliL3DigitRowData);
570       outsize += size;
571     }
572   return outsize;
573 }
574
575 Bool_t AliL3DataHandler::CompBinary2CompMemory(UInt_t &nrow,Byte_t *comp)
576 {
577   //Read RLE data from binary file into array comp.
578   rewind(fInBinary);
579   UInt_t size = GetFileSize() - 2;
580   Byte_t type;
581   if(fread(&type,1,1,fInBinary)!=1) return kFALSE;
582   if(type > 0)
583     {
584       LOG(AliL3Log::kError,"AliL3DataHandler::CompBinary2CompMemory","Filetype")
585         <<"Inputfile does not seem to contain 8 bit data : "<<type<<ENDLOG;
586       return kFALSE;
587     }
588   if(fread(&nrow,1,1,fInBinary)!=1) return kFALSE;
589   if(fread(comp,size,1,fInBinary)!=1) return kFALSE;
590
591   return kTRUE;
592 }
593
594 Bool_t AliL3DataHandler::CompMemory2CompBinary(UInt_t nrow,Byte_t *comp,UInt_t size)
595 {
596   //Write RLE data in comp to binary file.
597   //In order to distinguish these files from 10 bit data, 
598   //a zero is written to the beginning of the file.
599
600   Byte_t length = (Byte_t)nrow;
601   Byte_t type = 0;
602   if(fwrite(&type,1,1,fOutBinary)!=1) return kFALSE; //Write a zero, to mark that this file contains 8 bit data.
603   if(fwrite(&length,1,1,fOutBinary)!=1) return kFALSE;
604   if(fwrite(comp,size,1,fOutBinary)!=1) return kFALSE;
605   return kTRUE;
606 }