Moved from AliTransbit to AliL3Transbit.
[u/mrichter/AliRoot.git] / HLT / comp / AliL3Compress.cxx
1 //$Id$
2
3 // Author: Anders Vestbo <mailto:vestbo$fi.uib.no>
4 //*-- Copyright &copy ASV
5
6 #include "AliL3StandardIncludes.h"
7 #include <TH1.h>
8 #include <TH2.h>
9 #include <TRandom.h>
10
11 #include "AliL3Logging.h"
12 #include "AliL3Compress.h"
13 #include "AliL3TrackArray.h"
14 #include "AliL3ModelTrack.h"
15 #include "AliL3Transform.h"
16 #include "AliL3MemHandler.h"
17 #ifdef use_aliroot
18 #include "AliL3FileHandler.h"
19 #endif
20 #include "bitio.h"
21
22 //_____________________________________________________________
23 //
24 //  AliL3Compress
25 //
26 // Class for compressing and uncompressing data.
27
28 ClassImp(AliL3Compress)
29
30 AliL3Compress::AliL3Compress()
31 {
32   fTracks=0;
33   SetBitNumbers(0,0,0,0);
34   fSlice =0;
35   fPatch=0;
36   fDigits=0;
37   fDPt=0;
38 }
39
40 AliL3Compress::AliL3Compress(Int_t slice,Int_t patch,Char_t *path)
41 {
42   fSlice=slice;
43   fPatch=patch;
44   SetBitNumbers(0,0,0,0);
45   fTracks=0;
46   fDigits=0;
47   fDPt=0;
48   sprintf(fPath,"%s",path);
49 }
50
51 AliL3Compress::~AliL3Compress()
52 {
53   if(fTracks)
54     delete fTracks;
55   if(fDigits)
56     delete [] fDigits;
57   if(fDPt)
58     delete [] fDPt;
59 }
60
61 void AliL3Compress::SetBitNumbers(Int_t pad,Int_t time,Int_t charge,Int_t shape)
62 {
63   fNumPadBits=pad;
64   fNumTimeBits=time;
65   fNumChargeBits=charge;
66   fNumShapeBits=shape;
67 }
68
69 void AliL3Compress::WriteFile(AliL3TrackArray *tracks)
70 {
71   Char_t fname[100];
72   sprintf(fname,"%s/tracks_m_%d_%d.raw",fPath,fSlice,fPatch);
73   FILE *file = fopen(fname,"w");
74   Short_t ntracks = tracks->GetNTracks();
75   //cout<<"Writing "<<ntracks<<" tracks to file"<<endl;
76     
77   Int_t count=0;
78   AliL3ClusterModel *clusters=0;
79   AliL3TrackModel *model=0;
80   for(Int_t i=0; i<ntracks; i++)
81     {
82       AliL3ModelTrack *track = (AliL3ModelTrack*)tracks->GetCheckedTrack(i);
83       if(!track) continue;
84       
85       //Do not save useless tracks or clusters:
86       //if(track->CheckClustersQuality(2) == 0) 
87       //continue;
88       
89       track->FillModel();
90       model = track->GetModel();
91       if(model->fNClusters==0) continue;
92       clusters = track->GetClusters();
93       //cout<<"Writing "<<(int)model->fNClusters<<" clusters"<<endl;
94       if(fwrite(model,sizeof(AliL3TrackModel),1,file)!=1) break;
95       //cout<<"Writing "<<(int)model->fNClusters<<" clusters to file"<<endl;
96       if(fwrite(clusters,model->fNClusters*sizeof(AliL3ClusterModel),1,file)!=1) break;
97       //track->Print();
98       count++;
99       
100     }
101   cout<<"Wrote "<<count<<" tracks "<<endl;
102   fclose(file);
103 }
104
105 void AliL3Compress::ReadFile(Char_t which)
106 {
107   //Read the trackfile.
108
109   Char_t fname[100];
110   if(which == 'm')
111     sprintf(fname,"%s/tracks_m_%d_%d.raw",fPath,fSlice,fPatch);
112   else if(which == 'u')
113     sprintf(fname,"%s/tracks_u_%d_%d.raw",fPath,fSlice,fPatch);
114   else
115     {
116       cerr<<"AliL3Compress::ReadFile() : Wrong option"<<endl;
117       return;
118     }
119
120   FILE *file = fopen(fname,"r");
121   if(!file)
122     {
123       cerr<<"Cannot open file "<<fname<<endl;
124       return;
125     }
126
127   if(fTracks)
128     delete fTracks;
129   fTracks = new AliL3TrackArray("AliL3ModelTrack");
130   
131   //cout<<"Reading file "<<fname<<endl;
132   while(!feof(file))
133     {
134       AliL3ModelTrack *track = (AliL3ModelTrack*)fTracks->NextTrack();
135       track->Init(fSlice,fPatch);
136       AliL3TrackModel *model = track->GetModel();
137       AliL3ClusterModel *clusters = track->GetClusters();
138       //cout<<"Reading model "<<(int)model<<endl;
139       if(fread(model,sizeof(AliL3TrackModel),1,file)!=1) break;
140       //cout<<"Reading clusters "<<(int)clusters<<endl;
141       if(fread(clusters,(model->fNClusters)*sizeof(AliL3ClusterModel),1,file)!=1) break;
142       //cout<<"Filling track"<<endl;
143       track->FillTrack();
144       //track->Print();
145     }
146
147   fTracks->RemoveLast();
148   //cout<<"Read "<<fTracks->GetNTracks()<<" tracks from file"<<endl;
149   fclose(file);
150 }
151
152 void AliL3Compress::CompressFile()
153 {
154   if(fNumTimeBits==0)
155     {
156       cerr<<"AliL3Compress::CompressFile() : Bitnumbers not set"<<endl;
157       return;
158     }
159   
160   Char_t fname[100];
161   sprintf(fname,"%s/tracks_c_%d_%d.raw",fPath,fSlice,fPatch);
162   BIT_FILE *output = OpenOutputBitFile(fname);
163   
164   sprintf(fname,"%s/tracks_m_%d_%d.raw",fPath,fSlice,fPatch);
165   FILE *input = fopen(fname,"r");
166   if(!input)
167     {
168       cerr<<"AliL3Compress::CompressFile() : Error opening file: "<<fname<<endl;
169       return;
170     }
171
172   AliL3TrackModel track;
173   AliL3ClusterModel cluster;
174   Int_t temp;
175   Short_t power;
176   
177   Int_t timeo,pado,chargeo,shapeo;
178   timeo=pado=chargeo=shapeo=0;
179   while(!feof(input))
180     {
181       if(fread(&track,sizeof(AliL3TrackModel),1,input)!=1) break;
182       
183       if(output->mask != 0x80) //Write the current byte to file.
184         {
185           //cerr<<"\nAliL3Compress::CompressFile() : Writing overhead bits!!!"<<endl;
186           if(putc(output->rack,output->file )!=output->rack)
187             cerr<<"AliL3Compress::ComressFile : Error writing to bitfile"<<endl;
188           output->mask=0x80;
189           output->rack=0;
190         }
191       
192       //Write track parameters:
193       fwrite(&track,sizeof(AliL3TrackModel),1,output->file);
194       for(Int_t i=0; i<track.fNClusters; i++)
195         {
196           if(fread(&cluster,sizeof(AliL3ClusterModel),1,input)!=1) break;
197           
198           //Write empty flag:
199           temp = (Int_t)cluster.fPresent;
200           OutputBit(output,temp);
201           if(!temp) continue;
202           
203           //Write time information:
204           temp = (Int_t)cluster.fDTime;
205           if(temp<0)
206             OutputBit(output,0);
207           else
208             OutputBit(output,1);
209           power = 1<<(fNumTimeBits-1);
210           if(abs(temp)>=power)
211             {
212               timeo++;
213               temp=power - 1;
214             }
215           OutputBits(output,abs(temp),(fNumTimeBits-1));
216           
217           //Write pad information:
218           temp = (Int_t)cluster.fDPad;
219           if(temp<0)
220             OutputBit(output,0);
221           else
222             OutputBit(output,1);
223           power = 1<<(fNumPadBits-1);
224           if(abs(temp)>=power)
225             {
226               pado++;
227               temp=power - 1;
228             }
229           OutputBits(output,abs(temp),(fNumPadBits-1));
230           
231           //Write charge information:
232           temp = (Int_t)cluster.fDCharge;
233           if(temp<0)
234             OutputBit(output,0);
235           else
236             OutputBit(output,1);
237           power = 1<<(fNumChargeBits-1);
238           if(abs(temp)>=power)
239             {
240               chargeo++;
241               temp=power - 1;
242             }
243           OutputBits(output,abs(temp),(fNumChargeBits-1));
244                   
245           //Write shape information:
246           temp = (Int_t)cluster.fDSigmaY2;
247           if(temp<0)
248             OutputBit(output,0);
249           else
250             OutputBit(output,1);
251           power = 1<<(fNumShapeBits-1);
252           if(abs(temp) >= power)
253             {
254               shapeo++;
255               temp = power - 1;
256             }
257           OutputBits(output,abs(temp),(fNumShapeBits-1));
258           
259           temp = (Int_t)cluster.fDSigmaZ2;
260           if(temp<0)
261             OutputBit(output,0);
262           else
263             OutputBit(output,1);
264           power = 1<<(fNumShapeBits-1);
265           if(abs(temp) >= power)
266             {
267               shapeo++;
268               temp=power - 1;
269             }
270           OutputBits(output,abs(temp),(fNumShapeBits-1));
271         }
272     }
273   
274   fclose(input);
275   CloseOutputBitFile(output);
276
277   cout<<endl<<"Saturations: "<<endl
278       <<"Pad "<<pado<<endl
279       <<"Time "<<timeo<<endl
280       <<"Charge "<<chargeo<<endl
281       <<"Shape "<<shapeo<<endl;
282 }
283
284 void AliL3Compress::ExpandFile()
285 {
286   if(fNumTimeBits==0)
287     {
288       cerr<<"AliL3Compress::ExpandFile() : Bitnumbers not set"<<endl;
289       return;
290     }
291   
292   Char_t fname[100];
293   sprintf(fname,"%s/tracks_c_%d_%d.raw",fPath,fSlice,fPatch);
294   BIT_FILE *input = OpenInputBitFile(fname);
295   
296   sprintf(fname,"%s/tracks_u_%d_%d.raw",fPath,fSlice,fPatch);
297   FILE *output = fopen(fname,"w");
298   if(!output)
299     {
300       cerr<<"AliL3Compress::ExpandFile() : Error opening file: "<<fname<<endl;
301       return;
302     }
303
304   AliL3TrackModel trackmodel;
305   AliL3ClusterModel *clusters=0;
306   Int_t count=0;
307   
308   clusters = new AliL3ClusterModel[(AliL3Transform::GetNRows(fPatch))];
309   while(!feof(input->file))
310     {
311       input->mask=0x80;//make sure we read a new byte from file.
312       
313       //Read and write track:
314       if(fread(&trackmodel,sizeof(AliL3TrackModel),1,input->file)!=1) break;
315       fwrite(&trackmodel,sizeof(AliL3TrackModel),1,output);
316       
317       for(Int_t i=0; i<AliL3Transform::GetNRows(fPatch); i++)
318         {
319           Int_t temp,sign;
320           
321           //Read empty flag:
322           temp = InputBit(input);
323           if(!temp) 
324             {
325               clusters[i].fPresent=kFALSE;
326               continue;
327             }
328           clusters[i].fPresent=kTRUE;
329           
330           //Read time information:
331           sign=InputBit(input);
332           temp = InputBits(input,(fNumTimeBits-1));
333           if(!sign)
334             temp*=-1;
335           clusters[i].fDTime = temp;
336           
337           //Read pad information:
338           sign=InputBit(input);
339           temp = InputBits(input,(fNumPadBits-1));
340           if(!sign)
341             temp*=-1;
342           clusters[i].fDPad = temp;
343           
344           //Read charge information:
345           sign = InputBit(input);
346           temp=InputBits(input,(fNumChargeBits-1));
347           if(!sign)
348             temp*=-1;
349           clusters[i].fDCharge = temp;
350           
351           //Read shape information:
352           sign = InputBit(input);
353           temp = InputBits(input,(fNumShapeBits-1));
354           if(!sign)
355             temp*=-1;
356           clusters[i].fDSigmaY2 = temp;
357           
358           sign = InputBit(input);
359           temp = InputBits(input,(fNumShapeBits-1));
360           if(!sign)
361             temp*=-1;
362           clusters[i].fDSigmaZ2 = temp;
363         }
364       
365
366       count++;
367       fwrite(clusters,(trackmodel.fNClusters)*sizeof(AliL3ClusterModel),1,output);
368       
369     }
370   
371   delete [] clusters;
372   fclose(output);
373   CloseInputBitFile(input);
374 }
375
376 void AliL3Compress::CreateDigitArray(Int_t maxnumber)
377 {
378   fNUsed=0;
379   fNDigits = 0;
380   fMaxDigits=maxnumber;
381   if(fDigits) delete [] fDigits;
382   fDigits = new AliL3RandomDigitData[maxnumber];
383   if(fDPt) delete [] fDPt;
384   fDPt = new AliL3RandomDigitData*[maxnumber];
385 }
386
387 void AliL3Compress::RestoreData(Char_t which)
388 {
389   //Restore the data.
390   //which == u : restore compressed data
391   //which == m : restore uncompressed data
392   
393
394   ReadFile(which);
395   
396   CreateDigitArray(10000000);
397   
398   Float_t pad,time,sigmaY2,sigmaZ2;
399   Int_t charge,npads;
400   for(Int_t j=AliL3Transform::GetFirstRow(fPatch); j<=AliL3Transform::GetLastRow(fPatch); j++)
401     {
402       cout<<"Building clusters on row "<<j<<endl;
403       for(Int_t i=0; i<fTracks->GetNTracks(); i++)
404         {
405           AliL3ModelTrack *track = (AliL3ModelTrack*)fTracks->GetCheckedTrack(i);
406           if(!track) continue;
407           if(!track->GetPad(j,pad) || 
408              !track->GetTime(j,time) || 
409              !track->GetClusterCharge(j,charge) ||
410              !track->GetXYWidth(j,sigmaY2) || 
411              !track->GetZWidth(j,sigmaZ2))
412             continue;
413           npads = track->GetNPads(j);
414           CreateDigits(j,npads,pad,time,charge,sigmaY2,sigmaZ2);
415         }
416     }
417   
418   QSort(fDPt,0,fNDigits);
419 }
420
421 void AliL3Compress::PrintDigits(Int_t padrow)
422 {
423   Int_t pad,time,charge,row;
424   for(Int_t i=0; i<fNDigits; i++)
425     {
426       row = fDPt[i]->fRow;
427       if(padrow > 0)
428         if(row != padrow) continue;
429       pad = fDPt[i]->fPad;
430       time = fDPt[i]->fTime;
431       charge = fDPt[i]->fCharge;
432       if(i>0 && row != fDPt[i-1]->fRow)
433         cout<<"---Padrow "<<row<<"---"<<endl;
434       cout<<"Padrow "<<row<<" Pad "<<pad<<" time "<<time<<" charge "<<charge<<endl;
435     }
436 }
437
438 void AliL3Compress::WriteRestoredData()
439 {
440   Char_t fname[100];
441   
442   //Get the remaining raw data array:
443   AliL3MemHandler *mem = new AliL3MemHandler();
444   sprintf(fname,"%s/remains_%d_%d.raw",fPath,fSlice,fPatch);
445   mem->SetBinaryInput(fname);
446   UInt_t numdigits;
447   AliL3DigitRowData *origRow = mem->CompBinary2Memory(numdigits);
448   mem->CloseBinaryInput();
449   
450   //Allocate memory for the merged data:
451   UInt_t size = mem->GetAllocatedSize() + fNDigits*sizeof(AliL3DigitData);
452   cout<<"Allocating "<<size<<" bytes for merged data array "<<endl;
453   Byte_t *data = new Byte_t[size];
454   memset(data,0,size);
455   AliL3DigitRowData *tempRow = (AliL3DigitRowData*)data;
456
457   Int_t ndigits,action,charge;
458   UShort_t pad,time;
459       
460   UInt_t digit_counter;
461   Int_t row_counter=0;
462   for(Int_t i=AliL3Transform::GetFirstRow(fPatch); i<=AliL3Transform::GetLastRow(fPatch); i++)
463     {
464       tempRow->fRow = i;
465       ndigits=0;
466       AliL3DigitData *origDig = origRow->fDigitData;
467       AliL3DigitData *tempDig = tempRow->fDigitData;
468       if((Int_t)origRow->fRow != i)
469         cerr<<"AliL3Compress::WriteRestoredData() : Mismatching row numbering "<<(Int_t)origRow->fRow<<" "<<i<<endl;
470
471       //cout<<"Writing row "<<i<<" with "<<(Int_t)origRow->fNDigit<<" old digits"<<endl;
472       digit_counter=0;
473       
474       while(1)
475         {
476           while(digit_counter < origRow->fNDigit)
477             {
478               pad = origDig[digit_counter].fPad;
479               time = origDig[digit_counter].fTime;
480               charge = origDig[digit_counter].fCharge;
481               digit_counter++;
482               while( (action=ComparePoints(i,pad,time)) == 1)
483                 {
484                   tempDig[ndigits].fPad = fDPt[fNUsed]->fPad;
485                   tempDig[ndigits].fTime = fDPt[fNUsed]->fTime;
486                   tempDig[ndigits].fCharge = fDPt[fNUsed]->fCharge;
487                   ndigits++;
488                   fNUsed++;
489
490                 }
491               if(action == 0)
492                 {
493                   tempDig[ndigits].fPad = pad;
494                   tempDig[ndigits].fTime = time;
495                   tempDig[ndigits].fCharge = charge;
496                   ndigits++;
497                 }
498             }
499           
500           if(fNUsed >= fNDigits) 
501             {
502               //cerr<<"AliL3Compress::WriteRestoredData() : Array out of range : "<<fNUsed<<" "<<fNDigits<<endl;
503               break;
504             }
505           if(fDPt[fNUsed]->fRow != i) //we are on a new row
506             break;
507           tempDig[ndigits].fPad = fDPt[fNUsed]->fPad;
508           tempDig[ndigits].fTime = fDPt[fNUsed]->fTime;
509           tempDig[ndigits].fCharge = fDPt[fNUsed]->fCharge;
510           ndigits++;
511           fNUsed++;
512         }
513       //cout<<"Writing "<<ndigits<<" digits on row "<<i<<endl;
514       if(ndigits > 4)
515         {
516           row_counter++;
517         }
518       tempRow->fNDigit = ndigits;
519       Int_t size = sizeof(AliL3DigitData)*tempRow->fNDigit + sizeof(AliL3DigitRowData);
520       Byte_t *byte_pt = (Byte_t*)tempRow;
521       byte_pt += size;
522       tempRow = (AliL3DigitRowData*)byte_pt;
523       mem->UpdateRowPointer(origRow);
524     }
525   
526   if(row_counter != AliL3Transform::GetNRows(fPatch))
527     cerr<<"AliL3Compress::WriteRestoredData() : Written rows: "<<row_counter<<" total rows "<<AliL3Transform::GetNRows(fPatch)<<endl;
528   
529   mem->Free();  
530   sprintf(fname,"%s/restored_%d_%d.raw",fPath,fSlice,fPatch);
531   mem->SetBinaryOutput(fname);
532   mem->Memory2CompBinary((UInt_t)AliL3Transform::GetNRows(fPatch),(AliL3DigitRowData*)data);
533   mem->CloseBinaryOutput();
534   
535   delete [] data;
536   delete mem;
537   
538 }
539
540 void AliL3Compress::CreateDigits(Int_t row,Int_t npads,Float_t pad,Float_t time,Int_t charge,Float_t sigmaY2,Float_t sigmaZ2)
541 {
542   //Create raw data out of the cluster.
543     
544   if(npads == 1)//If there was only 1 pad, the xywidth is set to zero.
545     sigmaY2 = 0;
546   
547   if(sigmaY2 < 0 || sigmaZ2 <= 0)
548     {
549       cerr<<"AliL3Compress::CreateDigits() : Wrong sigmas : "<<sigmaY2<<" "<<sigmaZ2;
550       cerr<<" on row "<<row<<" pad "<<pad<<" time "<<time<<endl;
551       return;
552     }
553   
554   TRandom *random = new TRandom();
555   
556   Int_t entries=2000;
557   TH1F *hist1 = new TH1F("hist1","",AliL3Transform::GetNPads(row),0,AliL3Transform::GetNPads(row)-1);
558   TH1F *hist2 = new TH1F("hist2","",AliL3Transform::GetNTimeBins(),0,AliL3Transform::GetNTimeBins()-1);
559   TH2F *hist3 = new TH2F("hist3","",AliL3Transform::GetNPads(row),0,AliL3Transform::GetNPads(row)-1,AliL3Transform::GetNTimeBins(),0,AliL3Transform::GetNTimeBins()-1);
560
561
562   
563   //Create the distributions in pad and time:
564   for(Int_t i=0; i<entries; i++)
565     {
566       hist1->Fill(random->Gaus(pad,sqrt(sigmaY2)));
567       hist2->Fill(random->Gaus(time,sqrt(sigmaZ2)));
568     }
569     
570   //Create the cluster:
571   Int_t bin1,bin2;
572   Double_t content1,content2,dpad,dtime;
573   for(Int_t i=0; i<hist1->GetEntries(); i++)
574     {
575       bin1 = hist1->GetBin(i);
576       content1 = hist1->GetBinContent(bin1);
577       if((Int_t)content1==0) continue;
578       content1 = charge*content1/entries;
579       dpad = hist1->GetBinCenter(bin1);
580       for(Int_t j=0; j<hist2->GetEntries(); j++)
581         {
582           bin2 = hist2->GetBin(j);
583           content2 = hist2->GetBinContent(bin2);
584           if((Int_t)content2==0) continue;
585           content2 = content1*content2/entries;
586           dtime = hist2->GetBinCenter(bin2);
587           hist3->Fill(dpad,dtime,content2);
588         }
589     }
590   
591   Int_t local_dig=0;
592   //Fill it into the digit array:
593   for(Int_t i=0; i<hist3->GetNbinsX(); i++)
594     {
595       for(Int_t j=0; j<hist3->GetNbinsY(); j++)
596         {
597           bin1 = hist3->GetBin(i,j);
598           content1 = hist3->GetBinContent(bin1);
599           if((Int_t)content1 < 3) continue;
600           if(content1 >= 1024)
601             content1 = 1023;
602           if(fNDigits >= fMaxDigits)
603             {
604               cerr<<"AliL3Compress::CreateDigits() : Array index out of range : "<<fNDigits<<endl;
605               return;
606             }
607           fDigits[fNDigits].fCharge=(Int_t)content1;
608           fDigits[fNDigits].fRow = row;
609           fDigits[fNDigits].fPad = (Int_t)hist3->GetXaxis()->GetBinCenter(i);
610           fDigits[fNDigits].fTime = (Int_t)hist3->GetYaxis()->GetBinCenter(j);
611           fDPt[fNDigits] = &fDigits[fNDigits];
612           fNDigits++;
613           local_dig++;
614         }
615     }
616   //if(local_dig < 5)
617   //  cout<<"Small cluster "<<local_dig<<" pad "<<(Int_t)fDigits[fNDigits-1].fPad<<" time "<<(Int_t)fDigits[fNDigits-1].fTime<<endl;
618   
619   delete random;
620   delete hist1;
621   delete hist2;
622   delete hist3;
623 }
624
625 void AliL3Compress::PrintCompRatio()
626 {
627   Char_t fname[100];
628   sprintf(fname,"%s/remains_%d_%d.raw",fPath,fSlice,fPatch);
629   AliL3MemHandler *mem = new AliL3MemHandler();
630   if(!mem->SetBinaryInput(fname))
631     {
632       cerr<<"AliL3Compress::PrintCompRatio(): Error opening file: "<<fname<<endl;
633       return;
634     } 
635   UInt_t ndigits;
636   AliL3DigitRowData *rowPt = (AliL3DigitRowData*)mem->CompBinary2Memory(ndigits);
637   mem->CloseBinaryInput();
638
639   Int_t digit_counter=0;
640   for(Int_t i=AliL3Transform::GetFirstRow(fPatch); i<=AliL3Transform::GetLastRow(fPatch); i++)
641     {
642       digit_counter += rowPt->fNDigit;
643       mem->UpdateRowPointer(rowPt);
644     }
645   delete mem;
646   
647   sprintf(fname,"%s/tracks_c_%d_%d.raw",fPath,fSlice,fPatch);
648   FILE *file1 = fopen(fname,"r");
649   if(!file1)
650     {
651       cerr<<"AliL3Compress::PrintCompRatio(): Error opening file: "<<fname<<endl;
652       return;
653     }
654   fseek(file1,0,SEEK_END);
655   UInt_t filesize1 = (UInt_t)ftell(file1);
656   fclose(file1);
657   
658   sprintf(fname,"%s/digits_%d_%d.raw",fPath,fSlice,fPatch);
659   FILE *file2 = fopen(fname,"r");
660   if(!file2)
661     {
662       cerr<<"AliL3Compress::PrintCompRatio(): Error opening file: "<<fname<<endl;
663       return;
664     }
665   fseek(file2,0,SEEK_END);
666   UInt_t filesize2 = (UInt_t)ftell(file2);
667   fclose(file2);
668   
669   cout<<"----------------------"<<endl;
670   cout<<"Original file size   : "<<filesize2<<endl;
671   cout<<"Compressed file size : "<<filesize1<<endl;
672   cout<<"Remaining digits     : "<<digit_counter<<endl;
673   cout<<"Compression ratio    : "<<(Float_t)(filesize1 + (10*digit_counter)/8)/(Float_t)(filesize2)<<endl;
674   
675 }
676
677 void AliL3Compress::QSort(AliL3RandomDigitData **a, Int_t first, Int_t last)
678 {
679   
680   // Sort array of AliL3RandomDigitData pointers using a quicksort algorithm.
681   // Uses CompareDigits() to compare objects.
682   // Thanks to Root!
683   
684   static AliL3RandomDigitData *tmp;
685   static int i;           // "static" to save stack space
686   int j;
687   
688   while (last - first > 1) {
689     i = first;
690     j = last;
691     for (;;) {
692       while (++i < last && CompareDigits(a[i], a[first]) < 0)
693         ;
694       while (--j > first && CompareDigits(a[j], a[first]) > 0)
695         ;
696       if (i >= j)
697         break;
698       
699       tmp  = a[i];
700       a[i] = a[j];
701       a[j] = tmp;
702     }
703     if (j == first) {
704       ++first;
705       continue;
706     }
707     tmp = a[first];
708     a[first] = a[j];
709     a[j] = tmp;
710     if (j - first < last - (j + 1)) {
711       QSort(a, first, j);
712       first = j + 1;   // QSort(j + 1, last);
713     } else {
714       QSort(a, j + 1, last);
715       last = j;        // QSort(first, j);
716     }
717   }
718 }
719
720 void AliL3Compress::WriteRootFile(Char_t *newrootfile)
721 {
722 #ifdef use_aliroot
723   Char_t fname[100];
724   AliL3MemHandler *mem = new AliL3MemHandler();
725   sprintf(fname,"%s/restored_%d_%d.raw",fPath,fSlice,fPatch);
726   mem->SetBinaryInput(fname);
727   UInt_t ndigits;
728   AliL3DigitRowData *rowPt = (AliL3DigitRowData*)mem->CompBinary2Memory(ndigits);
729   mem->CloseBinaryInput();
730   
731   sprintf(fname,"%s/digitfile",fPath);
732   
733   AliL3FileHandler *file = new AliL3FileHandler();
734   if(!file->SetAliInput(fname))
735     {
736       cerr<<"AliL3Compress::WriteRootFile() : Error opening file: "<<fname<<endl;
737       return;
738     }
739
740   file->Init(fSlice,fPatch);
741   file->AliDigits2RootFile(rowPt,newrootfile);
742   file->CloseAliInput();
743
744   delete mem;
745   delete file;
746 #endif
747   return;
748 }