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