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