]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/src/AliL3MemHandler.cxx
New convention for the solenoid field
[u/mrichter/AliRoot.git] / HLT / src / AliL3MemHandler.cxx
1 // @(#) $Id$
2
3 // Author: Uli Frankenfeld <mailto:franken@fi.uib.no>, Anders Vestbo <mailto:vestbo$fi.uib.no>, Constantin Loizides <mailto:loizides@ikf.uni-frankfurt.de>
4 //*-- Copyright &copy ALICE HLT Group 
5
6 /** \class AliL3MemHandler 
7 <pre>
8 //_____________________________________________________________
9 // AliL3MemHandler
10 //
11 // The HLT Binary File handler 
12 //
13 //  This class does all the memory I/O handling of HLT binary files.
14 //  
15 //  Examples:
16 //  ---------
17 //
18 //  1) Reading a binary file:
19 //  
20 //  AliL3MemHandler file;
21 //  file.SetBinaryInput(filename);
22 //  file.Init(slice,patch);
23 //
24 //  UInt_t nrowss;
25 //  AliL3DigitRowData *data = file.CompBinary2Memory(nrows);
26 //  
27 //  for(int i=0; i<nrows; i++) 
28 //    {
29 //    
30 //    AliL3DigitData *dataPt = (AliL3DigitData*)data->fDigitData;
31 //    for(int j=0; j<data->fNDigit; j++) 
32 //      {
33 //        pad = dataPt[j].fPad;
34 //        time = dataPt[j].fTime;
35 //        charge = dataPt[j].fCharge;
36 //      }
37 //     
38 //    file.UpdateRowPointer(data);
39 //  
40 //    }
41 //  file.CloseBinaryInput();
42 //  ________________________
43 //  
44 //  2) Writing a binary file:
45 //  
46 //  //First of all you need to store the data in memory,
47 //  //and have a pointer to it of type AliL3DigitRowData.
48 //  //E.g. if you just want to write the data you read in example 1)
49 //  //into a new file, you can do the following:
50 //  
51 //  AliL3MemHandler newfile;
52 //  newfile.Init(slice,patch);
53 //  newfile.SetBinaryOutput(newfilename);
54 //  newfile.Memory2CompBinary((UInt_t)NumberOfRowsInPatch,(AliL3DigitRowData*)data);
55 //  newfile.CloseBinaryOutput();
56 //
57 //
58 // Compressed file format:
59 // -----------------------
60 //
61 // The data is RLE encoded and currently using _10_ bit range for the ADC-values.
62 </pre>
63 */  
64
65 #include "AliL3RootTypes.h"
66 #include "AliL3StandardIncludes.h"
67 #include "AliL3DigitData.h"
68 #include "AliL3Logging.h"
69 #include "AliL3Transform.h"
70 #include "AliL3TrackSegmentData.h"
71 #include "AliL3SpacePointData.h"
72 #include "AliL3TrackArray.h"
73 #include "AliL3MemHandler.h"
74
75 #if __GNUC__ >= 3
76 using namespace std;
77 #endif
78   
79 ClassImp(AliL3MemHandler)
80   
81 AliL3MemHandler::AliL3MemHandler()
82
83   //Constructor
84   fPt = 0;
85   fSize =0;
86   fInBinary = 0;
87   fOutBinary = 0;
88   fNRandom = 0;
89   Init(0,0);
90   fIsRandom = kFALSE;
91   fRandomDigits = 0;
92   fDPt =0;
93   fNGenerate = 0;
94   fNUsed = 0;
95   fNDigits = 0;
96   ResetROI();
97 }
98
99
100 AliL3MemHandler::~AliL3MemHandler()
101 {
102   //Destructor
103   if(fPt) delete[] fPt;
104   if(fRandomDigits) delete [] fRandomDigits;
105   if(fDPt) delete [] fDPt;
106 }
107
108 void AliL3MemHandler::Init(Int_t s,Int_t p, Int_t *r)
109 {
110   //init handler
111   fSlice=s;fPatch=p;
112   if(r) {
113     fRowMin=r[0];
114     fRowMax=r[1];
115   }else{
116      fRowMin=AliL3Transform::GetFirstRow(p);
117      fRowMax=AliL3Transform::GetLastRow(p); 
118   }
119   ResetROI();
120 }
121
122 void AliL3MemHandler::ResetROI()
123 {
124   //Resets the Look-up table for Region of Interest mode.
125   for(Int_t i=fRowMin; i<=fRowMax; i++)
126     {
127       fEtaMinTimeBin[i] = 0;
128       fEtaMaxTimeBin[i] = AliL3Transform::GetNTimeBins()-1;
129     }
130 }
131
132 void AliL3MemHandler::SetROI(Float_t *eta,Int_t */*slice*/)
133 {
134   // Init the Look-up table for the Region of Interest mode.
135   //   Here you can specify a certain etaregion, - all data
136   //   outside this region will be discarded:
137   //   eta[0] = mimium eta
138   //   eta[1] = maximum eta
139   //   slice[0] = mimumum slice
140   //   slice[1] = maximum slice
141
142
143   if(eta[1]==0)
144     {
145       LOG(AliL3Log::kWarning,"AliL3MemHandler::SetROI","Eta Values")
146         <<"Bad ROI parameters. IDIOT! "<<ENDLOG;
147       for(Int_t i=fRowMin; i<=fRowMax; i++)
148         {
149           fEtaMinTimeBin[i]=0;
150           fEtaMaxTimeBin[i]=0;
151         }
152       return;
153     }
154   
155   for(Int_t i=fRowMin; i<=fRowMax; i++)
156     {
157       Int_t sector,row;
158       Float_t xyz[3];
159       
160       Float_t thetamax = 2*atan(exp(-1.*eta[1]));
161       
162       xyz[0] = AliL3Transform::Row2X(i);
163       xyz[1]=0;
164       xyz[2] = xyz[0]/tan(thetamax);
165       AliL3Transform::Slice2Sector(fSlice,i,sector,row);
166       AliL3Transform::Local2Raw(xyz,sector,row);
167       
168       fEtaMinTimeBin[i] = (Int_t)xyz[2];
169       
170       if(eta[0]==0)
171         fEtaMaxTimeBin[i] = 445;
172       else
173         {
174           Float_t thetamin = 2*atan(exp(-1.*eta[0]));
175           xyz[0] = AliL3Transform::Row2X(i);
176           xyz[1] = AliL3Transform::GetMaxY(i);
177           Float_t radii = sqrt(pow(xyz[0],2) + pow(xyz[1],2));
178           xyz[2] = radii/tan(thetamin);
179           AliL3Transform::Local2Raw(xyz,sector,row);
180           fEtaMaxTimeBin[i] = (Int_t)xyz[2];
181         }
182     }
183   
184 }
185
186 Bool_t AliL3MemHandler::SetBinaryInput(char *name)
187 {
188   //Set the input binary file.
189   fInBinary = fopen(name,"r");
190   if(!fInBinary){
191     LOG(AliL3Log::kWarning,"AliL3MemHandler::SetBinaryInput","File Open")
192       <<"Error opening file "<<name<<ENDLOG;
193     return kFALSE;
194   }
195   return kTRUE;
196 }
197
198 Bool_t AliL3MemHandler::SetBinaryInput(FILE *file)
199 {
200   //Set the input binary file.
201   fInBinary = file;
202   if(!fInBinary){
203     LOG(AliL3Log::kWarning,"AliL3MemHandler::SetBinaryInput","File Open")
204     <<"Pointer to File = 0x0 "<<ENDLOG;
205     return kFALSE;
206   }
207   return kTRUE;
208 }
209
210 void AliL3MemHandler::CloseBinaryInput()
211 {
212   //Close the input file.
213   if(!fInBinary){
214     LOG(AliL3Log::kWarning,"AliL3MemHandler::CloseBinaryInput","File Close")
215       <<"Nothing to Close"<<ENDLOG;
216     return;
217   }
218   fclose(fInBinary);
219   fInBinary =0;
220 }
221
222 Bool_t AliL3MemHandler::SetBinaryOutput(char *name)
223 {
224   //Set the binary output file.
225     fOutBinary = fopen(name,"w");
226   if(!fOutBinary){
227     LOG(AliL3Log::kWarning,"AliL3MemHandler::SetBinaryOutput","File Open")
228       <<"Pointer to File = 0x0 "<<ENDLOG;
229     return kFALSE;
230   }
231   return kTRUE;
232 }
233
234 Bool_t AliL3MemHandler::SetBinaryOutput(FILE *file)
235 {
236   //Set the binary output file.
237     fOutBinary = file;
238   if(!fOutBinary){
239     LOG(AliL3Log::kWarning,"AliL3MemHandler::SetBinaryOutput","File Open")
240       <<"Pointer to File = 0x0 "<<ENDLOG;
241     return kFALSE;
242   }
243   return kTRUE;
244 }
245
246 void AliL3MemHandler::CloseBinaryOutput()
247 {
248   //close binary  
249   if(!fOutBinary){
250     LOG(AliL3Log::kWarning,"AliL3MemHandler::CloseBinaryOutPut","File Close")
251       <<"Nothing to Close"<<ENDLOG;
252     return;
253   }
254   fclose(fOutBinary);
255   fOutBinary =0;
256 }
257
258 UInt_t AliL3MemHandler::GetFileSize()
259 {
260   //Returns the file size in bytes of the input file.
261   if(!fInBinary){
262     LOG(AliL3Log::kWarning,"AliL3MemHandler::GetFileSize","File")
263       <<"No Input File"<<ENDLOG;
264     return 0;
265   }
266   fseek(fInBinary,0,SEEK_END);
267   UInt_t size = (UInt_t) ftell(fInBinary);
268   rewind(fInBinary);
269   return size; 
270 }
271
272 Byte_t *AliL3MemHandler::Allocate()
273 {
274   //Allocate
275   return Allocate(GetFileSize()); 
276 }
277
278 Byte_t *AliL3MemHandler::Allocate(AliL3TrackArray *array)
279 {
280   //Allocate memory for tracks in memory. Used by TrackArray2Binary()
281   if(!array){
282     LOG(AliL3Log::kWarning,"AliL3MemHandler::Allocate","Memory")
283       <<"Pointer to AliL3TrackArray = 0x0 "<<ENDLOG;
284     return 0;
285   }
286   return Allocate(array->GetOutSize()); 
287 }
288
289 Byte_t *AliL3MemHandler::Allocate(UInt_t size)
290 {
291   //Allocate memory of size in bytes.
292   if(fPt){
293     LOG(AliL3Log::kWarning,"AliL3MemHandler::Allocate","Memory")
294       <<"Delete Memory"<<ENDLOG;
295     Free();
296   } 
297   fPt = new Byte_t[size];
298   fSize = size;
299   memset(fPt,0,fSize);
300   LOG(AliL3Log::kDebug,"AliL3MemHandler::Allocate","Memory")
301   <<AliL3Log::kDec<<"Allocate "<<size<<" Bytes of Memory"<<ENDLOG;
302   return fPt;
303 }
304
305 void AliL3MemHandler::Free()
306 {
307   //Clear the memory, if allocated.
308   if(!fPt){
309     //    LOG(AliL3Log::kInformational,"AliL3MemHandler::Free","Memory")
310     //      <<"No Memory allocated - can't Free"<<ENDLOG;
311     return;
312   }  
313   delete[] fPt;
314   fPt = 0;
315   fSize =0;
316 }
317
318 ///////////////////////////////////////// Random
319 void AliL3MemHandler::SetRandomSeed()
320 {
321   //If you are adding random data to the original data.
322   time_t *tp=0;
323   SetRandomSeed(time(tp));
324 }
325
326 void AliL3MemHandler::SetRandomCluster(Int_t maxnumber)
327 {
328   //If you are adding random data to the original data.
329   
330   fIsRandom = kTRUE;
331   fNRandom = maxnumber;
332   fNDigits = 0;
333   if(fRandomDigits) delete [] fRandomDigits;
334   fRandomDigits = new AliL3RandomDigitData[fNRandom*9];
335   if(fDPt) delete [] fDPt;
336   fDPt = new AliL3RandomDigitData *[fNRandom*9];
337 }
338
339 void AliL3MemHandler::QSort(AliL3RandomDigitData **a, Int_t first, Int_t last)
340 {
341
342    // Sort array of AliL3RandomDigitData pointers using a quicksort algorithm.
343    // Uses CompareDigits() to compare objects.
344    // Thanks to Root!
345
346    static AliL3RandomDigitData *tmp;
347    static int i;           // "static" to save stack space
348    int j;
349
350    while (last - first > 1) {
351       i = first;
352       j = last;
353       for (;;) {
354          while (++i < last && CompareDigits(a[i], a[first]) < 0)
355             ;
356          while (--j > first && CompareDigits(a[j], a[first]) > 0)
357             ;
358          if (i >= j)
359             break;
360
361          tmp  = a[i];
362          a[i] = a[j];
363          a[j] = tmp;
364       }
365       if (j == first) {
366          ++first;
367          continue;
368       }
369       tmp = a[first];
370       a[first] = a[j];
371       a[j] = tmp;
372
373       if (j - first < last - (j + 1)) {
374         QSort(a, first, j);
375         first = j + 1;   // QSort(j + 1, last);
376       } else {
377         QSort(a, j + 1, last);
378         last = j;        // QSort(first, j);
379       }
380    }
381 }
382
383 UInt_t AliL3MemHandler::GetRandomSize() const
384 {
385   //get random size
386   Int_t nrandom = 0;
387   for(Int_t r=fRowMin;r<=fRowMax;r++){
388     Int_t npad=AliL3Transform::GetNPads(r);
389     nrandom  += Int_t (fNGenerate * ((Double_t) npad/141.));
390   }
391   return 9 * nrandom * sizeof(AliL3DigitData);
392 }
393
394 void AliL3MemHandler::Generate(Int_t row)
395 {
396   //Generate random data on row, if you didn't 
397   //ask for this, nothing happens here.
398   
399   if(!fIsRandom) return;
400   ResetRandom();
401   fNDigits = 0;
402   Int_t npad=AliL3Transform::GetNPads(row);
403   Int_t ntime = fEtaMaxTimeBin[row] - fEtaMinTimeBin[row];
404   Int_t nrandom  = Int_t (fNGenerate * ((Double_t) npad/141.) * 
405                           (Double_t) ntime/(Double_t) AliL3Transform::GetNTimeBins() );
406   
407   for(Int_t n=0;n<nrandom;n++){
408     Int_t pad = (int)((float)rand()/RAND_MAX*npad);
409     Int_t time =(int)((float)rand()/RAND_MAX*ntime+fEtaMinTimeBin[row] );
410     Int_t charge = (int)((float)rand()/RAND_MAX*AliL3Transform::GetADCSat());
411     DigitizePoint(row,pad,time,charge);
412   }
413   QSort(fDPt,0,fNDigits);
414 }
415
416
417 void AliL3MemHandler::DigitizePoint(Int_t row, Int_t pad, 
418                                     Int_t time,Int_t charge)
419 {
420   //Making one single random cluster.
421   for(Int_t j=-1;j<2;j++){
422     for(Int_t k=-1;k<2;k++){
423       Int_t dcharge = charge;
424       if(j) dcharge /=2;
425       if(k) dcharge /=2;
426       if(dcharge<10) continue;
427       Int_t dpad  = j + pad;
428       Int_t dtime = k + time;
429       
430       if(dpad<0||dpad>=AliL3Transform::GetNPads(row))  continue;
431       if(dtime<0||dtime>=AliL3Transform::GetNTimeBins()) continue;
432       
433       fRandomDigits[fNDigits].fCharge = dcharge;
434       fRandomDigits[fNDigits].fRow = row;
435       fRandomDigits[fNDigits].fPad = dpad;
436       fRandomDigits[fNDigits].fTime = dtime;
437       fDPt[fNDigits] = &fRandomDigits[fNDigits];
438       fNDigits++;
439     }
440   }
441 }
442
443 ///////////////////////////////////////// Digit IO  
444 Bool_t AliL3MemHandler::Memory2Binary(UInt_t nrow,AliL3DigitRowData *data)
445 {
446   //Write data to the outputfile as is. No run-length encoding is done.
447   
448   if(!fOutBinary){
449     LOG(AliL3Log::kWarning,"AliL3MemHandler::Memory2Binary","File")
450       <<"No Output File"<<ENDLOG;
451     return kFALSE;
452   }
453   if(!data){
454     LOG(AliL3Log::kWarning,"AliL3MemHandler::Memory2Binary","Memory")
455       <<"Pointer to AliL3DigitRowData = 0x0 "<<ENDLOG;
456     return kFALSE;
457   }
458   
459   AliL3DigitRowData *rowPt = data; 
460   Int_t outsize = 0;
461   for(UInt_t i=0;i<nrow;i++){
462     Int_t size = sizeof(AliL3DigitData) * rowPt->fNDigit 
463       + sizeof(AliL3DigitRowData);
464     outsize += size;
465     fwrite(rowPt,size,1,fOutBinary);
466     Byte_t  *bytePt =(Byte_t *) rowPt;
467     bytePt += size;
468     rowPt = (AliL3DigitRowData *) bytePt;
469   }
470   LOG(AliL3Log::kDebug,"AliL3MemHandler::Memory2Binary","Memory")
471     <<AliL3Log::kDec<<"Wrote "<<outsize<<" Bytes to Memory ("
472     <<nrow<<" Rows)"<<ENDLOG;
473   return kTRUE;
474 }
475
476 Bool_t AliL3MemHandler::Binary2Memory(UInt_t & nrow,AliL3DigitRowData *data)
477 {
478   //Read inputfile into memory as is, and store it in data. 
479   // No run-length encoding is assumed.
480
481   if(!fInBinary){
482     LOG(AliL3Log::kWarning,"AliL3MemHandler::Binary2Memory","File")
483       <<"No Input File"<<ENDLOG;
484     return kFALSE;
485   }
486   if(!data){
487     LOG(AliL3Log::kWarning,"AliL3MemHandler::Binary2Memory","Memory")
488       <<"Pointer to AliL3DigitRowData = 0x0 "<<ENDLOG;
489     return kFALSE;
490   }
491   rewind(fInBinary);
492   AliL3DigitRowData *rowPt = data;
493   UInt_t rowcount = 0;
494   Int_t outsize =0;
495   while(!feof(fInBinary)){
496     Byte_t  *bytePt =(Byte_t *) rowPt;
497
498     if(fread(rowPt,sizeof(AliL3DigitRowData),1,fInBinary)!=1) break;
499
500     bytePt += sizeof(AliL3DigitRowData);
501     outsize += sizeof(AliL3DigitRowData);
502
503     Int_t size = sizeof(AliL3DigitData) * rowPt->fNDigit;
504
505     //if(fread(bytePt,size,1,fInBinary)!=1) break;
506     fread(bytePt,size,1,fInBinary);
507     bytePt += size;
508     outsize += size;
509     rowPt = (AliL3DigitRowData *) bytePt;
510     rowcount++;
511   }  
512   nrow= rowcount;
513     LOG(AliL3Log::kDebug,"AliL3MemHandler::Binary2Memory","Memory")
514     <<AliL3Log::kDec<<"Wrote "<<outsize<<" Bytes to Memory ("
515     <<rowcount<<" Rows)"<<ENDLOG;
516   return kTRUE;
517 }
518
519 void AliL3MemHandler::AddData(AliL3DigitData *data,UInt_t & ndata,
520                               UInt_t /*row*/,UShort_t pad,UShort_t time,UShort_t charge) const
521 {
522   //add some data
523   data[ndata].fPad = pad;
524   data[ndata].fTime = time;
525   data[ndata].fCharge = charge;
526   ndata++;
527 }
528
529 void AliL3MemHandler::AddRandom(AliL3DigitData *data, UInt_t & ndata)
530 {
531   //add some random data
532   data[ndata].fPad = fDPt[fNUsed]->fPad;
533   data[ndata].fTime = fDPt[fNUsed]->fTime;
534   data[ndata].fCharge = fDPt[fNUsed]->fCharge;
535   ndata++;
536   fNUsed++;
537 }
538
539 void AliL3MemHandler::MergeDataRandom(AliL3DigitData *data, UInt_t & ndata,
540                                       UInt_t row, UShort_t pad, UShort_t time, UShort_t charge)
541 {
542   //merge random data
543   data[ndata].fPad = pad;
544   data[ndata].fTime = time;
545   data[ndata].fCharge = charge;
546   while(ComparePoints(row,pad,time)==0){
547     Int_t ch = data[ndata].fCharge + fDPt[fNUsed]->fCharge;
548     if(charge>=AliL3Transform::GetADCSat()) ch = AliL3Transform::GetADCSat();
549     data[ndata].fCharge = ch;
550     fNUsed++;
551   }
552   ndata++;
553 }
554
555 void AliL3MemHandler::AddDataRandom(AliL3DigitData *data, UInt_t & ndata,
556                    UInt_t row, UShort_t pad, UShort_t time, UShort_t charge)
557 {
558   //add data random
559   Int_t action;
560   while((action=ComparePoints(row,pad,time))==1){
561     AddRandom(data,ndata);
562   }
563   if(action==0){
564     MergeDataRandom(data,ndata,row,pad,time,charge);
565   }
566   if(action<0){
567     AddData(data,ndata,row,pad,time,charge);
568   }  
569 }
570
571 void AliL3MemHandler::Write(UInt_t *comp, UInt_t & index, 
572                             UInt_t & subindex, UShort_t value) const
573 {
574   //write compressed data
575   UInt_t shift[3] = {0,10,20};
576   if(subindex==0) comp[index] =0; //clean up memory
577   comp[index] |= (value&0x03ff)<<shift[subindex];
578   if(subindex == 2){
579     subindex = 0;
580     index++;
581   }
582   else subindex++;
583 }
584
585 UShort_t AliL3MemHandler::Read(UInt_t *comp, UInt_t & index, UInt_t & subindex) const
586
587   //read compressed data
588   UInt_t shift[3] = {0,10,20};
589   UShort_t value = (comp[index]>>shift[subindex])&0x03ff;
590   if(subindex == 2){
591     subindex = 0;
592     index++;
593   }
594   else subindex++;
595   
596   return value;
597 }
598
599 UShort_t AliL3MemHandler::Test(UInt_t *comp, 
600                                UInt_t index, UInt_t  subindex) const
601 {
602   //supi dupi test
603   UInt_t shift[3] = {0,10,20};
604   return (comp[index]>>shift[subindex])&0x03ff;
605 }
606
607 Int_t AliL3MemHandler::Memory2CompMemory(UInt_t nrow,
608                                          AliL3DigitRowData *data,UInt_t *comp)
609 {
610   //Performs run-length encoding on data stored in memory pointed to by data.
611   //The compressed data is written to comp.
612   if(!comp){
613     LOG(AliL3Log::kWarning,"AliL3MemHandler::Memory2CompMemory","Memory")
614       <<"Pointer to compressed data = 0x0 "<<ENDLOG;
615     return 0;
616   }
617   if(!data){
618     LOG(AliL3Log::kWarning,"AliL3MemHandler::Memory2CompMemory","Memory")
619       <<"Pointer to AliL3DigitRowData = 0x0 "<<ENDLOG;
620     return 0;
621   }
622   AliL3DigitRowData *rowPt = data;
623   UInt_t index=0;
624   UInt_t subindex=0;
625   
626   for(UInt_t i=0;i<nrow;i++){
627     UShort_t value = rowPt->fRow;
628     Write(comp,index,subindex,value);
629     UShort_t maxpad=0; 
630     UShort_t npad=0;
631     Int_t ddd[1000];
632     for(Int_t d=0;d<200;d++) ddd[d]=0;
633     for(UInt_t dig=0;dig<rowPt->fNDigit;dig++){
634       if(rowPt->fDigitData[dig].fPad <200){ 
635         ddd[rowPt->fDigitData[dig].fPad]++;
636       }
637     }
638     for(Int_t d=0;d<200;d++){ 
639       if(ddd[d]){
640         npad++;
641         maxpad =d;
642       }
643     }
644     Write(comp,index,subindex,npad);
645     UInt_t digit=0;
646     for(UShort_t pad=0;pad <= maxpad;pad++){
647       if(digit>=rowPt->fNDigit || rowPt->fDigitData[digit].fPad !=  pad)
648         continue;
649       Write(comp,index,subindex,pad);
650 //    write zero if time != 0
651       if(digit<rowPt->fNDigit && rowPt->fDigitData[digit].fPad == pad){
652         if(rowPt->fDigitData[digit].fTime>0){
653           Write(comp,index,subindex,0);
654           Write(comp,index,subindex,rowPt->fDigitData[digit].fTime);
655         }
656       }
657       while(digit<rowPt->fNDigit && rowPt->fDigitData[digit].fPad == pad){
658         UShort_t charge = rowPt->fDigitData[digit].fCharge;
659         if(charge>=1023){
660           charge=1023;
661         }
662         Write(comp,index,subindex,charge);
663         if(digit+1<rowPt->fNDigit&&rowPt->fDigitData[digit+1].fPad == pad){
664           if(rowPt->fDigitData[digit].fTime +1 !=
665                      rowPt->fDigitData[digit+1].fTime){
666             Write(comp,index,subindex,0);
667             UShort_t nzero = rowPt->fDigitData[digit+1].fTime - 
668                              (rowPt->fDigitData[digit].fTime +1);
669             Write(comp,index,subindex,nzero);
670           }  
671         }
672         digit++;
673       }
674       Write(comp,index,subindex,0);
675       Write(comp,index,subindex,0);
676     }
677     
678     Int_t size = sizeof(AliL3DigitData) * rowPt->fNDigit+
679                                             sizeof(AliL3DigitRowData);
680     Byte_t  *bytePt =(Byte_t *) rowPt;
681     bytePt += size;
682     rowPt = (AliL3DigitRowData *) bytePt;
683   }
684   while(subindex)
685     Write(comp,index,subindex,0);
686   return index * sizeof(UInt_t);
687 }
688
689 Int_t AliL3MemHandler::CompMemory2Memory(UInt_t  nrow,
690                                          AliL3DigitRowData *data,UInt_t *comp)
691 {
692   //Uncompress the run-length encoded data in memory pointed to by comp, and
693   //  store it in data.
694
695   if(!comp){
696     LOG(AliL3Log::kWarning,"AliL3MemHandler::CompMemory2Memory","Memory")
697       <<"Pointer to compressed data = 0x0 "<<ENDLOG;
698     return 0;
699   }
700   if(!data){
701     LOG(AliL3Log::kWarning,"AliL3MemHandler::CompMemory2Memory","Memory")
702       <<"Pointer to AliL3DigitRowData = 0x0 "<<ENDLOG;
703     return 0;
704   }
705   Int_t outsize=0;
706   
707   AliL3DigitRowData *rowPt = data;
708   UInt_t index=0;
709   UInt_t subindex=0;
710   
711   for(UInt_t i=0;i<nrow;i++){
712     UInt_t ndigit=0;
713     UInt_t row =Read(comp,index,subindex);
714     rowPt->fRow=row;
715     Generate(row);
716     UShort_t npad = Read(comp,index,subindex);
717     for(UShort_t p=0;p<npad;p++){
718       UShort_t charge;
719       UShort_t time =0;
720       UShort_t pad = Read(comp,index,subindex);
721       if(Test(comp,index,subindex)==0){
722         Read(comp,index,subindex);
723         if( (time = Read(comp,index,subindex)) == 0 ){
724           continue;
725         }
726       }
727       for(;;){
728         while( (charge=Read(comp,index,subindex)) != 0){
729           if(time>=fEtaMinTimeBin[row]&&time<=fEtaMaxTimeBin[row])
730             //AddData(rowPt->fDigitData,ndigit,row,pad,time,charge);
731             //seems we are using this function... but dont know why
732             AddDataRandom(rowPt->fDigitData,ndigit,row,pad,time,charge);
733           time++;
734         }
735         UShort_t tshift = Read(comp,index,subindex);
736         if(tshift == 0) break;
737         time += tshift;
738       }
739     }
740     rowPt->fNDigit = ndigit;
741     Int_t size = sizeof(AliL3DigitData) * rowPt->fNDigit+
742       sizeof(AliL3DigitRowData);
743     Byte_t  *bytePt =(Byte_t *) rowPt;
744     bytePt += size;
745     outsize += size;
746     rowPt = (AliL3DigitRowData *) bytePt;
747   }
748   return outsize;
749 }
750
751 UInt_t AliL3MemHandler::GetCompMemorySize(UInt_t nrow,AliL3DigitRowData *data) const
752 {
753   //Return the size of RLE data, after compressing data.
754   
755   if(!data){
756     LOG(AliL3Log::kWarning,"AliL3MemHandler::GetCompMemorySize","Memory")
757       <<"Pointer to AliL3DigitRowData = 0x0 "<<ENDLOG;
758     return 0;
759   }
760   AliL3DigitRowData *rowPt = data;
761   UInt_t index=0;
762   
763   for(UInt_t i=0;i<nrow;i++){
764     index++;
765     UShort_t maxpad=0; 
766     UShort_t npad=0;
767     Int_t ddd[1000];
768     for(Int_t d=0;d<200;d++) ddd[d]=0;
769     for(UInt_t dig=0;dig<rowPt->fNDigit;dig++){
770       if(rowPt->fDigitData[dig].fPad <200){ 
771         ddd[rowPt->fDigitData[dig].fPad]++;
772       }
773     }
774     for(Int_t d=0;d<200;d++){ 
775       if(ddd[d]){
776         npad++;
777         maxpad =d;
778       }
779     }
780     index++;
781     UInt_t digit=0;
782     for(UShort_t pad=0;pad <= maxpad;pad++){
783       if(digit>=rowPt->fNDigit || rowPt->fDigitData[digit].fPad !=  pad)
784         continue;
785       index++;
786       //    write zero if time != 0
787       if(digit<rowPt->fNDigit && rowPt->fDigitData[digit].fPad == pad){
788         if(rowPt->fDigitData[digit].fTime>0){
789           index++;
790           index++;
791         }
792       }
793       while(digit<rowPt->fNDigit && rowPt->fDigitData[digit].fPad == pad){
794         index++;
795         if(digit+1<rowPt->fNDigit&&rowPt->fDigitData[digit+1].fPad == pad){
796           if(rowPt->fDigitData[digit].fTime +1 !=
797                      rowPt->fDigitData[digit+1].fTime){
798             index++;
799             index++;
800           }  
801         }
802         digit++;
803       }
804       index++;
805       index++;
806     }
807
808     Int_t size = sizeof(AliL3DigitData) * rowPt->fNDigit+
809                                             sizeof(AliL3DigitRowData);
810     Byte_t  *bytePt =(Byte_t *) rowPt;
811     bytePt += size;
812     rowPt = (AliL3DigitRowData *) bytePt;
813   }
814   while(index%3)
815     index++;
816   return (index/3) * sizeof(UInt_t);
817 }
818
819 UInt_t AliL3MemHandler::GetMemorySize(UInt_t nrow,UInt_t *comp) const
820 {
821   //get memory size
822   if(!comp){
823     LOG(AliL3Log::kWarning,"AliL3MemHandler::GetMemorySize","Memory")
824     <<"Pointer to compressed data = 0x0 "<<ENDLOG;
825     return 0;
826   }
827   Int_t outsize=0;
828
829   UInt_t index=0;
830   UInt_t subindex=0;
831
832   for(UInt_t i=0;i<nrow;i++){
833     UInt_t ndigit=0;
834     Read(comp,index,subindex);
835     UShort_t npad = Read(comp,index,subindex);
836     for(UShort_t p=0;p<npad;p++){
837       Read(comp,index,subindex);
838       if(Test(comp,index,subindex)==0){
839         Read(comp,index,subindex);
840         if(Read(comp,index,subindex)== 0) continue;
841       }
842       for(;;){
843         while(Read(comp,index,subindex)!=0) ndigit++;
844         if(Read(comp,index,subindex)==0) break;
845       }
846     }
847     Int_t size = sizeof(AliL3DigitData) * ndigit+
848                                         sizeof(AliL3DigitRowData);
849     outsize += size;
850   }
851    
852   return outsize;
853 }
854
855 UInt_t AliL3MemHandler::GetNRow(UInt_t *comp,UInt_t size)
856 {
857   //get number of rows
858   if(!comp){
859     LOG(AliL3Log::kWarning,"AliL3MemHandler::GetNRow","Memory")
860       <<"Pointer to compressed data = 0x0 "<<ENDLOG;
861     return 0;
862   }
863   size = size /4;
864   UInt_t nrow=0;
865   UInt_t index=0;
866   UInt_t subindex=0;
867   while(index<size-1){ //don't start with last word
868     nrow++;
869     UInt_t ndigit=0;
870     Read(comp,index,subindex);
871     UShort_t npad = Read(comp,index,subindex);
872     for(UShort_t p=0;p<npad;p++){
873       Read(comp,index,subindex);
874       if(Test(comp,index,subindex)==0){
875         Read(comp,index,subindex);
876         if(Read(comp,index,subindex)==0)continue;
877       }
878       for(;;){
879         while(Read(comp,index,subindex)!=0) ndigit++;
880         if(Read(comp,index,subindex)==0) break;
881       }
882     }
883   }
884   if(index==size-1){  //last word
885     if(subindex<2){
886       if(Read(comp,index,subindex)!=0) nrow++;
887     }
888   }
889   return nrow;
890 }
891
892 Bool_t AliL3MemHandler::CompMemory2CompBinary(UInt_t nrow,UInt_t *comp,
893                                               UInt_t size)
894 {
895   //Write the RLE data in comp to the output file.
896   
897   if(!fOutBinary){
898     LOG(AliL3Log::kWarning,"AliL3MemHandler::CompMemory2CompBinary","File")
899     <<"No Output File"<<ENDLOG;
900     return kFALSE;
901   }
902   if(!comp){
903     LOG(AliL3Log::kWarning,"AliL3MemHandler::CompMemory2CompBinary","Memory")
904     <<"Pointer to compressed data = 0x0 "<<ENDLOG;
905     return kFALSE;
906   }
907   if(size==0)
908     size=GetMemorySize(nrow,comp);
909   if(!size){
910     LOG(AliL3Log::kWarning,"AliL3MemHandler::CompMemory2CompBinary","Memory")
911     <<"Memory size = 0 "<<ENDLOG;
912     return kFALSE;
913   }
914   UInt_t length = size/sizeof(UInt_t);
915   fwrite(&length,sizeof(UInt_t),1,fOutBinary);  
916   fwrite(comp,size,1,fOutBinary);
917   return kTRUE;
918 }
919
920 Bool_t AliL3MemHandler::CompBinary2CompMemory(UInt_t & nrow,UInt_t *comp)
921 {
922   //Read the RLE data from file, and store it in comp. No unpacking yet.
923
924   if(!fInBinary){
925     LOG(AliL3Log::kWarning,"AliL3MemHandler::CompBinary2CompMemory","File")
926       <<"No Output File"<<ENDLOG;
927     return kFALSE;
928   }
929   if(!comp){
930     LOG(AliL3Log::kWarning,"AliL3MemHandler::CompBinary2CompMemory","Memory")
931       <<"Pointer to compressed data = 0x0 "<<ENDLOG;
932     return kFALSE;
933   }
934   rewind(fInBinary);
935   UInt_t length;
936   if(fread(&length,sizeof(UInt_t),1,fInBinary)!=1) return kFALSE;
937   UInt_t size = length*sizeof(UInt_t);
938   if(fread(comp,size,1,fInBinary)!=1) return kFALSE;
939   // now find the number of dig
940   nrow =  GetNRow(comp,size);
941   return kTRUE;
942 }
943
944 AliL3DigitRowData *AliL3MemHandler::CompBinary2Memory(UInt_t & nrow)
945 {
946   // Read the RLE inputfile, unpack it and return the pointer to it.
947   AliL3MemHandler * handler = new AliL3MemHandler();
948   handler->SetBinaryInput(fInBinary);
949   UInt_t *comp =(UInt_t *)handler->Allocate();
950   handler->CompBinary2CompMemory(nrow,comp);
951   UInt_t size = GetMemorySize(nrow,comp);
952   AliL3DigitRowData *data = (AliL3DigitRowData *)Allocate(size);
953   CompMemory2Memory(nrow,data,comp);
954   handler->Free();
955   delete handler;
956   return data;  
957 }
958
959 Bool_t AliL3MemHandler::Memory2CompBinary(UInt_t nrow,AliL3DigitRowData *data)
960 {
961   //Perform RLE on the data, and write it to the output file.
962   Bool_t out = kTRUE;
963   AliL3MemHandler * handler = new AliL3MemHandler();
964   UInt_t size = GetCompMemorySize(nrow,data);
965   UInt_t *comp =(UInt_t *)handler->Allocate(size);
966   Memory2CompMemory(nrow,data,comp);
967   CompMemory2CompBinary(nrow,comp,size);
968   handler->Free();
969   delete handler;
970   return out;
971 }
972
973
974 ///////////////////////////////////////// Point IO  
975 Bool_t AliL3MemHandler::Memory2Binary(UInt_t npoint,AliL3SpacePointData *data)
976 {
977   //Writing spacepoints stored in data to the outputfile.
978   if(!fOutBinary){
979     LOG(AliL3Log::kWarning,"AliL3MemHandler::Memory2Binary","File")
980       <<"No Output File"<<ENDLOG;
981     return kFALSE;
982   }
983   if(!data){
984     LOG(AliL3Log::kWarning,"AliL3MemHandler::Memory2Binary","Memory")
985       <<"Pointer to AliL3SpacePointData = 0x0 "<<ENDLOG;
986     return kFALSE;
987   }
988   UInt_t size = npoint*sizeof(AliL3SpacePointData);
989   fwrite(data,size,1,fOutBinary);
990   
991   return kTRUE;
992 }
993
994 Bool_t AliL3MemHandler::Transform(UInt_t npoint,AliL3SpacePointData *data,Int_t slice)
995 {
996   //Transform the space points in data, to global coordinates in slice.
997   if(!data){
998     LOG(AliL3Log::kWarning,"AliL3MemHandler::Transform","Memory")
999     <<"Pointer to AliL3SpacePointData = 0x0 "<<ENDLOG;
1000     return kFALSE;
1001   }
1002   
1003   for(UInt_t i=0;i<npoint;i++){
1004     Float_t xyz[3];
1005     xyz[0] = data[i].fX;
1006     xyz[1] = data[i].fY;
1007     xyz[2] = data[i].fZ;
1008     AliL3Transform::Local2Global(xyz,slice);
1009     data[i].fX = xyz[0];
1010     data[i].fY = xyz[1];
1011     data[i].fZ = xyz[2];
1012   }
1013   return kTRUE;
1014 }
1015
1016 Bool_t AliL3MemHandler::Binary2Memory(UInt_t & npoint,AliL3SpacePointData *data)
1017 {
1018   //Read the space points in inputfile, and store it in data.
1019   if(!fInBinary){
1020     LOG(AliL3Log::kWarning,"AliL3MemHandler::Binary2Memory","File")
1021     <<"No Input File"<<ENDLOG;
1022     return kFALSE;
1023   }
1024   if(!data){
1025     LOG(AliL3Log::kWarning,"AliL3MemHandler::Binary2Memory","Memory")
1026     <<"Pointer to AliL3SpacePointData = 0x0 "<<ENDLOG;
1027     return kFALSE;
1028   }
1029
1030   Int_t size = GetFileSize(); 
1031   npoint = size/sizeof(AliL3SpacePointData);
1032   if(size==0) {
1033     LOG(AliL3Log::kWarning,"AliL3MemHandler::Binary2Memory","File")
1034     <<"File Size == 0"<<ENDLOG;
1035     return kFALSE;
1036   }
1037
1038   if(fread(data,size,1,fInBinary)!=1){
1039     LOG(AliL3Log::kFatal,"AliL3MemHandler::Binary2Memory","File")
1040     <<"File Read Error "<<ENDLOG;
1041     return kFALSE;
1042   }
1043   if(size%sizeof(AliL3SpacePointData)){
1044     LOG(AliL3Log::kFatal,"AliL3MemHandler::Binary2Memory","File Size")
1045     <<"File Size wrong "<<ENDLOG;
1046     return kFALSE; 
1047   }
1048   LOG(AliL3Log::kDebug,"AliL3MemHandler::Binary2Memory","File")
1049   <<AliL3Log::kDec<<"Wrote  "<<size<<" Bytes to Memory"<<ENDLOG;
1050   return kTRUE;
1051 }
1052
1053 ///////////////////////////////////////// Track IO  
1054 Bool_t AliL3MemHandler::Memory2Binary(UInt_t ntrack,AliL3TrackSegmentData *data)
1055 {
1056   //Write the tracks stored in data, to outputfile.
1057   if(!fOutBinary){
1058     LOG(AliL3Log::kWarning,"AliL3MemHandler::Memory2Binary","File")
1059     <<"No Output File"<<ENDLOG;
1060     return kFALSE;
1061   }
1062   if(!data){
1063     LOG(AliL3Log::kWarning,"AliL3MemHandler::Memory2Binary","Memory")
1064     <<"Pointer to AliL3TrackSegmentData = 0x0 "<<ENDLOG;
1065     return kFALSE;
1066   }
1067   AliL3TrackSegmentData *trackPt = data;
1068   for(UInt_t i=0;i<ntrack;i++){
1069     Int_t size=sizeof(AliL3TrackSegmentData)+trackPt->fNPoints*sizeof(UInt_t); 
1070     fwrite(trackPt,size,1,fOutBinary);
1071     Byte_t *bytePt = (Byte_t*) trackPt;
1072     bytePt += size; 
1073     trackPt = (AliL3TrackSegmentData*) bytePt;
1074   }
1075   LOG(AliL3Log::kDebug,"AliL3MemHandler::Memory2Binary","File")
1076   <<AliL3Log::kDec<<"Wrote  "<<ntrack<<" Tracks to File"<<ENDLOG;
1077   
1078   return kTRUE;
1079 }
1080
1081 Bool_t AliL3MemHandler::Binary2Memory(UInt_t & ntrack,AliL3TrackSegmentData *data)
1082 {
1083   //Read the tracks in inputfile, and store it in data.
1084   if(!fInBinary){
1085     LOG(AliL3Log::kWarning,"AliL3MemHandler::Binary2Memory","File")
1086     <<"No Input File"<<ENDLOG;
1087     return kFALSE;
1088   }
1089   if(!data){
1090     LOG(AliL3Log::kWarning,"AliL3MemHandler::Binary2Memory","Memory")
1091     <<"Pointer to AliL3TrackSegmentData = 0x0 "<<ENDLOG;
1092     return kFALSE;
1093   }
1094
1095   ntrack=0;
1096   AliL3TrackSegmentData *trackPt = data;
1097   rewind(fInBinary);
1098
1099   while(!feof(fInBinary)){
1100     if(fread(trackPt,sizeof(AliL3TrackSegmentData),1,fInBinary)!=1) break;
1101     Int_t size=trackPt->fNPoints*sizeof(UInt_t);
1102     if(fread(trackPt->fPointIDs,size,1,fInBinary)!=1) break;
1103     Byte_t *bytePt = (Byte_t*) trackPt;
1104     bytePt += sizeof(AliL3TrackSegmentData)+size;
1105     trackPt = (AliL3TrackSegmentData*) bytePt;
1106     ntrack++; 
1107   }
1108   LOG(AliL3Log::kDebug,"AliL3MemHandler::Binary2Memory","File")
1109   <<AliL3Log::kDec<<"Wrote  "<<ntrack<<" Tracks to Memory"<<ENDLOG;
1110   return kTRUE;
1111 }
1112
1113 Bool_t AliL3MemHandler::TrackArray2Binary(AliL3TrackArray *array)
1114 {
1115   //Write the trackarray to the outputfile.
1116   if(!fOutBinary){
1117     LOG(AliL3Log::kWarning,"AliL3MemHandler::TrackArray2Binary","File")
1118     <<"No Output File"<<ENDLOG;
1119     return kFALSE;
1120   }
1121   if(!array){
1122     LOG(AliL3Log::kWarning,"AliL3MemHandler::TrackArray2Binary","Memory")
1123     <<"Pointer to AliL3TrackArray = 0x0 "<<ENDLOG;
1124     return kFALSE;
1125   }
1126   AliL3TrackSegmentData *data = (AliL3TrackSegmentData *)Allocate(array);
1127
1128   UInt_t ntrack;
1129   TrackArray2Memory(ntrack,data,array);
1130   Memory2Binary(ntrack,data);
1131   Free();
1132   return kTRUE;
1133 }
1134
1135 Bool_t AliL3MemHandler::Binary2TrackArray(AliL3TrackArray *array)
1136 {
1137   //Read the tracks in inputfile, and fill it in trackarray. 
1138   //array should already be constructed.
1139   if(!fInBinary){
1140     LOG(AliL3Log::kWarning,"AliL3MemHandler::Binary2TrackArray","File")
1141     <<"No Input File"<<ENDLOG;
1142     return kFALSE;
1143   }
1144   if(!array){
1145     LOG(AliL3Log::kWarning,"AliL3MemHandler::Binary2TrackArray","Memory")
1146     <<"Pointer to AliL3TrackArray = 0x0 "<<ENDLOG;
1147     return kFALSE;
1148   }
1149   AliL3TrackSegmentData *data = (AliL3TrackSegmentData *)Allocate();
1150   UInt_t ntrack;
1151   Binary2Memory(ntrack,data);
1152   Memory2TrackArray(ntrack,data,array);  
1153   Free();
1154   return kTRUE;
1155 }
1156
1157 Bool_t AliL3MemHandler::TrackArray2Memory(UInt_t & ntrack,AliL3TrackSegmentData *data,AliL3TrackArray *array) const
1158 {
1159   //Fill the trackarray into the AliTrackSegmentData structures before writing to outputfile.
1160   if(!data){
1161     LOG(AliL3Log::kWarning,"AliL3MemHandler::TrackArray2Memory","Memory")
1162     <<"Pointer to AliL3TrackSegmentData = 0x0 "<<ENDLOG;
1163     return kFALSE;
1164   }
1165   if(!array){
1166     LOG(AliL3Log::kWarning,"AliL3MemHandler::TrackArray2Memory","Memory")
1167     <<"Pointer to AliL3TrackArray = 0x0 "<<ENDLOG;
1168     return kFALSE;
1169   }
1170
1171   array->WriteTracks(ntrack,data);
1172   return kTRUE;
1173 }
1174
1175 Bool_t AliL3MemHandler::Memory2TrackArray(UInt_t ntrack,AliL3TrackSegmentData *data,AliL3TrackArray *array) const
1176 {
1177   //Fill the tracks in data into trackarray.
1178   
1179   if(!data){
1180     LOG(AliL3Log::kWarning,"AliL3MemHandler::Memory2TrackArray","Memory")
1181     <<"Pointer to AliL3TrackSegmentData = 0x0 "<<ENDLOG;
1182     return kFALSE;
1183   }
1184   if(!array){
1185     LOG(AliL3Log::kWarning,"AliL3MemHandler::Memory2TrackArray","Memory")
1186     <<"Pointer to AliL3TrackArray = 0x0 "<<ENDLOG;
1187     return kFALSE;
1188   }
1189   array->FillTracks(ntrack,data);
1190   return kTRUE;
1191 }
1192
1193 Bool_t AliL3MemHandler::Memory2TrackArray(UInt_t ntrack,AliL3TrackSegmentData *data,AliL3TrackArray *array,Int_t slice) const
1194 {
1195   //Fill the tracks in data into trackarray, and rotate the tracks to global coordinates.
1196     
1197   if(!data){
1198     LOG(AliL3Log::kWarning,"AliL3MemHandler::Memory2TrackArray","Memory")
1199     <<"Pointer to AliL3TrackSegmentData = 0x0 "<<ENDLOG;
1200     return kFALSE;
1201   }
1202   if(!array){
1203     LOG(AliL3Log::kWarning,"AliL3MemHandler::Memory2TrackArray","Memory")
1204     <<"Pointer to AliL3TrackArray = 0x0 "<<ENDLOG;
1205     return kFALSE;
1206   }
1207   array->FillTracks(ntrack,data,slice);
1208   return kTRUE;
1209 }
1210
1211 void AliL3MemHandler::UpdateRowPointer(AliL3DigitRowData *&tempPt)
1212 {
1213   //Update the data pointer to the next padrow in memory.
1214   
1215   Byte_t *tmp = (Byte_t*)tempPt;
1216   Int_t size = sizeof(AliL3DigitRowData) + tempPt->fNDigit*sizeof(AliL3DigitData);
1217   tmp += size;
1218   tempPt = (AliL3DigitRowData*)tmp;
1219 }
1220
1221 Int_t  AliL3MemHandler::ComparePoints(UInt_t /*row*/,UShort_t pad,UShort_t time) const
1222 {
1223   //compare two points
1224   if(fNUsed>=fNDigits) return -2;
1225
1226   if(pad==fDPt[fNUsed]->fPad&&time==fDPt[fNUsed]->fTime) return 0;
1227
1228   if(pad<fDPt[fNUsed]->fPad) return -1;
1229   if(pad==fDPt[fNUsed]->fPad&&time<fDPt[fNUsed]->fTime)  return -1;
1230
1231   return 1;
1232 }
1233
1234 Int_t AliL3MemHandler::CompareDigits(AliL3RandomDigitData *a,AliL3RandomDigitData *b) const
1235 {
1236   //compare two digits
1237   if(a->fPad==b->fPad && a->fTime == b->fTime) return 0;
1238
1239   if(a->fPad<b->fPad) return -1;
1240   if(a->fPad==b->fPad && a->fTime<b->fTime) return -1;
1241   
1242   return 1;
1243 }