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