3 // Author: Anders Vestbo <mailto:vestbo$fi.uib.no>
4 //*-- Copyright © ASV
6 #include "AliL3StandardIncludes.h"
11 #include "AliL3Logging.h"
12 #include "AliL3Compress.h"
13 #include "AliL3TrackArray.h"
14 #include "AliL3ModelTrack.h"
15 #include "AliL3Transform.h"
16 #include "AliL3MemHandler.h"
18 #include "AliL3FileHandler.h"
22 //_____________________________________________________________
26 // Class for compressing and uncompressing data.
28 ClassImp(AliL3Compress)
30 AliL3Compress::AliL3Compress()
33 SetBitNumbers(0,0,0,0);
41 AliL3Compress::AliL3Compress(Int_t slice,Int_t patch,Char_t *path,Bool_t writeshape)
45 SetBitNumbers(0,0,0,0);
49 sprintf(fPath,"%s",path);
50 fWriteShape=writeshape;
53 AliL3Compress::~AliL3Compress()
63 void AliL3Compress::SetBitNumbers(Int_t pad,Int_t time,Int_t charge,Int_t shape)
67 fNumChargeBits=charge;
71 void AliL3Compress::WriteFile(AliL3TrackArray *tracks)
74 sprintf(fname,"%s/comp/tracks_m_%d_%d.raw",fPath,fSlice,fPatch);
75 FILE *file = fopen(fname,"w");
78 cerr<<"AliL3Compress::WriteFile : Error opening file "<<fname<<endl;
81 Short_t ntracks = tracks->GetNTracks();
82 //cout<<"Writing "<<ntracks<<" tracks to file"<<endl;
85 AliL3ClusterModel *clusters=0;
86 AliL3TrackModel *model=0;
87 for(Int_t i=0; i<ntracks; i++)
89 AliL3ModelTrack *track = (AliL3ModelTrack*)tracks->GetCheckedTrack(i);
92 //Do not save useless tracks or clusters:
93 if(track->GetNPresentClusters() == 0)
97 model = track->GetModel();
98 if(model->fNClusters==0) continue;
99 clusters = track->GetClusters();
100 //cout<<"Writing "<<(int)model->fNClusters<<" clusters"<<endl;
101 if(fwrite(model,sizeof(AliL3TrackModel),1,file)!=1) break;
102 //cout<<"Writing "<<(int)model->fNClusters<<" clusters to file"<<endl;
103 if(fwrite(clusters,model->fNClusters*sizeof(AliL3ClusterModel),1,file)!=1) break;
108 cout<<"Wrote "<<count<<" tracks "<<endl;
112 void AliL3Compress::ReadFile(Char_t which)
114 //Read the trackfile.
118 sprintf(fname,"%s/comp/tracks_m_%d_%d.raw",fPath,fSlice,fPatch);
119 else if(which == 'u')
120 sprintf(fname,"%s/comp/tracks_u_%d_%d.raw",fPath,fSlice,fPatch);
123 cerr<<"AliL3Compress::ReadFile() : Wrong option"<<endl;
127 FILE *file = fopen(fname,"r");
130 cerr<<"AliL3Compress::ReadFile : Cannot open file "<<fname<<endl;
136 fTracks = new AliL3TrackArray("AliL3ModelTrack");
138 //cout<<"Reading file "<<fname<<endl;
141 AliL3ModelTrack *track = (AliL3ModelTrack*)fTracks->NextTrack();
142 track->Init(fSlice,fPatch);
143 AliL3TrackModel *model = track->GetModel();
144 AliL3ClusterModel *clusters = track->GetClusters();
145 if(fread(model,sizeof(AliL3TrackModel),1,file)!=1) break;
146 if(fread(clusters,(model->fNClusters)*sizeof(AliL3ClusterModel),1,file)!=1) break;
150 fTracks->RemoveLast();
151 //cout<<"Read "<<fTracks->GetNTracks()<<" tracks from file"<<endl;
155 void AliL3Compress::CompressFile()
159 cerr<<"AliL3Compress::CompressFile() : Bitnumbers not set"<<endl;
164 sprintf(fname,"%s/comp/tracks_c_%d_%d.raw",fPath,fSlice,fPatch);
165 BIT_FILE *output = OpenOutputBitFile(fname);
167 sprintf(fname,"%s/comp/tracks_m_%d_%d.raw",fPath,fSlice,fPatch);
168 FILE *input = fopen(fname,"r");
171 cerr<<"AliL3Compress::CompressFile() : Error opening file: "<<fname<<endl;
175 AliL3TrackModel track;
176 AliL3ClusterModel cluster;
180 Int_t timeo,pado,chargeo,shapeo;
181 timeo=pado=chargeo=shapeo=0;
184 if(fread(&track,sizeof(AliL3TrackModel),1,input)!=1) break;
186 if(output->mask != 0x80) //Write the current byte to file.
188 //cerr<<"\nAliL3Compress::CompressFile() : Writing overhead bits!!!"<<endl;
189 if(putc(output->rack,output->file )!=output->rack)
190 cerr<<"AliL3Compress::ComressFile : Error writing to bitfile"<<endl;
195 //Write track parameters:
196 fwrite(&track,sizeof(AliL3TrackModel),1,output->file);
197 for(Int_t i=0; i<track.fNClusters; i++)
199 if(fread(&cluster,sizeof(AliL3ClusterModel),1,input)!=1) break;
202 temp = (Int_t)cluster.fPresent;
203 OutputBit(output,temp);
206 //Write time information:
207 temp = (Int_t)cluster.fDTime;
212 power = 1<<(fNumTimeBits-1);
218 OutputBits(output,abs(temp),(fNumTimeBits-1));
220 //Write pad information:
221 temp = (Int_t)cluster.fDPad;
226 power = 1<<(fNumPadBits-1);
232 OutputBits(output,abs(temp),(fNumPadBits-1));
234 //Write charge information:
235 temp = (Int_t)cluster.fDCharge;
236 power = 1<<(fNumChargeBits);
242 OutputBits(output,abs(temp),(fNumChargeBits));
246 //Write shape information:
247 temp = (Int_t)cluster.fDSigmaY2;
252 power = 1<<(fNumShapeBits-1);
253 if(abs(temp) >= power)
258 OutputBits(output,abs(temp),(fNumShapeBits-1));
260 temp = (Int_t)cluster.fDSigmaZ2;
265 power = 1<<(fNumShapeBits-1);
266 if(abs(temp) >= power)
271 OutputBits(output,abs(temp),(fNumShapeBits-1));
277 CloseOutputBitFile(output);
279 cout<<endl<<"Saturations: "<<endl
281 <<"Time "<<timeo<<endl
282 <<"Charge "<<chargeo<<endl
283 <<"Shape "<<shapeo<<endl;
286 void AliL3Compress::ExpandFile()
290 cerr<<"AliL3Compress::ExpandFile() : Bitnumbers not set"<<endl;
295 sprintf(fname,"%s/comp/tracks_c_%d_%d.raw",fPath,fSlice,fPatch);
296 BIT_FILE *input = OpenInputBitFile(fname);
298 sprintf(fname,"%s/comp/tracks_u_%d_%d.raw",fPath,fSlice,fPatch);
299 FILE *output = fopen(fname,"w");
302 cerr<<"AliL3Compress::ExpandFile() : Error opening file: "<<fname<<endl;
306 AliL3TrackModel trackmodel;
307 AliL3ClusterModel *clusters=0;
310 clusters = new AliL3ClusterModel[(AliL3Transform::GetNRows(fPatch))];
311 while(!feof(input->file))
313 input->mask=0x80;//make sure we read a new byte from file.
315 //Read and write track:
316 if(fread(&trackmodel,sizeof(AliL3TrackModel),1,input->file)!=1) break;
317 fwrite(&trackmodel,sizeof(AliL3TrackModel),1,output);
319 memset(clusters,0,AliL3Transform::GetNRows(fPatch)*sizeof(AliL3ClusterModel));
320 for(Int_t i=0; i<AliL3Transform::GetNRows(fPatch); i++)
325 temp = InputBit(input);
328 clusters[i].fPresent=kFALSE;
331 clusters[i].fPresent=kTRUE;
333 //Read time information:
334 sign=InputBit(input);
335 temp = InputBits(input,(fNumTimeBits-1));
338 clusters[i].fDTime = temp;
340 //Read pad information:
341 sign=InputBit(input);
342 temp = InputBits(input,(fNumPadBits-1));
345 clusters[i].fDPad = temp;
347 //Read charge information:
348 temp=InputBits(input,(fNumChargeBits));
349 clusters[i].fDCharge = temp;
353 //Read shape information:
354 sign = InputBit(input);
355 temp = InputBits(input,(fNumShapeBits-1));
358 clusters[i].fDSigmaY2 = temp;
360 sign = InputBit(input);
361 temp = InputBits(input,(fNumShapeBits-1));
364 clusters[i].fDSigmaZ2 = temp;
368 fwrite(clusters,(trackmodel.fNClusters)*sizeof(AliL3ClusterModel),1,output);
374 CloseInputBitFile(input);
377 void AliL3Compress::CreateDigitArray(Int_t maxnumber)
381 fMaxDigits=maxnumber;
382 if(fDigits) delete [] fDigits;
383 fDigits = new AliL3RandomDigitData[maxnumber];
384 if(fDPt) delete [] fDPt;
385 fDPt = new AliL3RandomDigitData*[maxnumber];
388 void AliL3Compress::RestoreData(Char_t which)
391 //which == u : restore compressed data
392 //which == m : restore uncompressed data
396 cerr<<"AliL3Compress::RestoreData : Not implemented without shape info "<<endl;
402 CreateDigitArray(10000000);
404 Float_t pad,time,sigmaY2,sigmaZ2;
406 for(Int_t j=AliL3Transform::GetFirstRow(fPatch); j<=AliL3Transform::GetLastRow(fPatch); j++)
408 cout<<"Building clusters on row "<<j<<endl;
409 for(Int_t i=0; i<fTracks->GetNTracks(); i++)
411 AliL3ModelTrack *track = (AliL3ModelTrack*)fTracks->GetCheckedTrack(i);
413 if(!track->GetPad(j,pad) ||
414 !track->GetTime(j,time) ||
415 !track->GetClusterCharge(j,charge) ||
416 !track->GetXYWidth(j,sigmaY2) ||
417 !track->GetZWidth(j,sigmaZ2))
419 npads = track->GetNPads(j);
420 CreateDigits(j,npads,pad,time,charge,sigmaY2,sigmaZ2);
424 QSort(fDPt,0,fNDigits);
427 void AliL3Compress::PrintDigits(Int_t padrow)
429 Int_t pad,time,charge,row;
430 for(Int_t i=0; i<fNDigits; i++)
434 if(row != padrow) continue;
436 time = fDPt[i]->fTime;
437 charge = fDPt[i]->fCharge;
438 if(i>0 && row != fDPt[i-1]->fRow)
439 cout<<"---Padrow "<<row<<"---"<<endl;
440 cout<<"Padrow "<<row<<" Pad "<<pad<<" time "<<time<<" charge "<<charge<<endl;
444 void AliL3Compress::WriteRestoredData()
448 //Get the remaining raw data array:
449 AliL3MemHandler *mem = new AliL3MemHandler();
450 sprintf(fname,"%s/comp/remains_%d_%d.raw",fPath,fSlice,fPatch);
451 mem->SetBinaryInput(fname);
453 AliL3DigitRowData *origRow = mem->CompBinary2Memory(numdigits);
454 mem->CloseBinaryInput();
456 //Allocate memory for the merged data:
457 UInt_t size = mem->GetAllocatedSize() + fNDigits*sizeof(AliL3DigitData);
458 cout<<"Allocating "<<size<<" bytes for merged data array "<<endl;
459 Byte_t *data = new Byte_t[size];
461 AliL3DigitRowData *tempRow = (AliL3DigitRowData*)data;
463 Int_t ndigits,action,charge;
466 UInt_t digit_counter;
468 for(Int_t i=AliL3Transform::GetFirstRow(fPatch); i<=AliL3Transform::GetLastRow(fPatch); i++)
472 AliL3DigitData *origDig = origRow->fDigitData;
473 AliL3DigitData *tempDig = tempRow->fDigitData;
474 if((Int_t)origRow->fRow != i)
475 cerr<<"AliL3Compress::WriteRestoredData() : Mismatching row numbering "<<(Int_t)origRow->fRow<<" "<<i<<endl;
477 //cout<<"Writing row "<<i<<" with "<<(Int_t)origRow->fNDigit<<" old digits"<<endl;
482 while(digit_counter < origRow->fNDigit)
484 pad = origDig[digit_counter].fPad;
485 time = origDig[digit_counter].fTime;
486 charge = origDig[digit_counter].fCharge;
488 while( (action=ComparePoints(i,pad,time)) == 1)
490 tempDig[ndigits].fPad = fDPt[fNUsed]->fPad;
491 tempDig[ndigits].fTime = fDPt[fNUsed]->fTime;
492 tempDig[ndigits].fCharge = fDPt[fNUsed]->fCharge;
499 tempDig[ndigits].fPad = pad;
500 tempDig[ndigits].fTime = time;
501 tempDig[ndigits].fCharge = charge;
506 if(fNUsed >= fNDigits)
508 //cerr<<"AliL3Compress::WriteRestoredData() : Array out of range : "<<fNUsed<<" "<<fNDigits<<endl;
511 if(fDPt[fNUsed]->fRow != i) //we are on a new row
513 tempDig[ndigits].fPad = fDPt[fNUsed]->fPad;
514 tempDig[ndigits].fTime = fDPt[fNUsed]->fTime;
515 tempDig[ndigits].fCharge = fDPt[fNUsed]->fCharge;
519 //cout<<"Writing "<<ndigits<<" digits on row "<<i<<endl;
524 tempRow->fNDigit = ndigits;
525 Int_t size = sizeof(AliL3DigitData)*tempRow->fNDigit + sizeof(AliL3DigitRowData);
526 Byte_t *byte_pt = (Byte_t*)tempRow;
528 tempRow = (AliL3DigitRowData*)byte_pt;
529 mem->UpdateRowPointer(origRow);
532 if(row_counter != AliL3Transform::GetNRows(fPatch))
533 cerr<<"AliL3Compress::WriteRestoredData() : Written rows: "<<row_counter<<" total rows "<<AliL3Transform::GetNRows(fPatch)<<endl;
536 sprintf(fname,"%s/comp/restored_%d_%d.raw",fPath,fSlice,fPatch);
537 mem->SetBinaryOutput(fname);
538 mem->Memory2CompBinary((UInt_t)AliL3Transform::GetNRows(fPatch),(AliL3DigitRowData*)data);
539 mem->CloseBinaryOutput();
546 void AliL3Compress::CreateDigits(Int_t row,Int_t npads,Float_t pad,Float_t time,Int_t charge,Float_t sigmaY2,Float_t sigmaZ2)
548 //Create raw data out of the cluster.
550 if(npads == 1)//If there was only 1 pad, the xywidth is set to zero.
553 if(sigmaY2 < 0 || sigmaZ2 <= 0)
555 cerr<<"AliL3Compress::CreateDigits() : Wrong sigmas : "<<sigmaY2<<" "<<sigmaZ2;
556 cerr<<" on row "<<row<<" pad "<<pad<<" time "<<time<<endl;
560 TRandom *random = new TRandom();
563 TH1F *hist1 = new TH1F("hist1","",AliL3Transform::GetNPads(row),0,AliL3Transform::GetNPads(row)-1);
564 TH1F *hist2 = new TH1F("hist2","",AliL3Transform::GetNTimeBins(),0,AliL3Transform::GetNTimeBins()-1);
565 TH2F *hist3 = new TH2F("hist3","",AliL3Transform::GetNPads(row),0,AliL3Transform::GetNPads(row)-1,AliL3Transform::GetNTimeBins(),0,AliL3Transform::GetNTimeBins()-1);
569 //Create the distributions in pad and time:
570 for(Int_t i=0; i<entries; i++)
572 hist1->Fill(random->Gaus(pad,sqrt(sigmaY2)));
573 hist2->Fill(random->Gaus(time,sqrt(sigmaZ2)));
576 //Create the cluster:
578 Double_t content1,content2,dpad,dtime;
579 for(Int_t i=0; i<hist1->GetEntries(); i++)
581 bin1 = hist1->GetBin(i);
582 content1 = hist1->GetBinContent(bin1);
583 if((Int_t)content1==0) continue;
584 content1 = charge*content1/entries;
585 dpad = hist1->GetBinCenter(bin1);
586 for(Int_t j=0; j<hist2->GetEntries(); j++)
588 bin2 = hist2->GetBin(j);
589 content2 = hist2->GetBinContent(bin2);
590 if((Int_t)content2==0) continue;
591 content2 = content1*content2/entries;
592 dtime = hist2->GetBinCenter(bin2);
593 hist3->Fill(dpad,dtime,content2);
598 //Fill it into the digit array:
599 for(Int_t i=0; i<hist3->GetNbinsX(); i++)
601 for(Int_t j=0; j<hist3->GetNbinsY(); j++)
603 bin1 = hist3->GetBin(i,j);
604 content1 = hist3->GetBinContent(bin1);
605 if((Int_t)content1 < 3) continue;
608 if(fNDigits >= fMaxDigits)
610 cerr<<"AliL3Compress::CreateDigits() : Array index out of range : "<<fNDigits<<endl;
613 fDigits[fNDigits].fCharge=(Int_t)content1;
614 fDigits[fNDigits].fRow = row;
615 fDigits[fNDigits].fPad = (Int_t)hist3->GetXaxis()->GetBinCenter(i);
616 fDigits[fNDigits].fTime = (Int_t)hist3->GetYaxis()->GetBinCenter(j);
617 fDPt[fNDigits] = &fDigits[fNDigits];
623 // cout<<"Small cluster "<<local_dig<<" pad "<<(Int_t)fDigits[fNDigits-1].fPad<<" time "<<(Int_t)fDigits[fNDigits-1].fTime<<endl;
631 void AliL3Compress::PrintCompRatio()
634 sprintf(fname,"%s/comp/remains_%d_%d.raw",fPath,fSlice,fPatch);
635 AliL3MemHandler *mem = new AliL3MemHandler();
636 if(!mem->SetBinaryInput(fname))
638 cerr<<"AliL3Compress::PrintCompRatio(): Error opening file: "<<fname<<endl;
642 AliL3DigitRowData *rowPt = (AliL3DigitRowData*)mem->CompBinary2Memory(ndigits);
643 mem->CloseBinaryInput();
645 Int_t digit_counter=0;
646 for(Int_t i=AliL3Transform::GetFirstRow(fPatch); i<=AliL3Transform::GetLastRow(fPatch); i++)
648 digit_counter += rowPt->fNDigit;
649 mem->UpdateRowPointer(rowPt);
653 sprintf(fname,"%s/comp/tracks_c_%d_%d.raw",fPath,fSlice,fPatch);
654 FILE *file1 = fopen(fname,"r");
657 cerr<<"AliL3Compress::PrintCompRatio(): Error opening file: "<<fname<<endl;
660 fseek(file1,0,SEEK_END);
661 UInt_t filesize1 = (UInt_t)ftell(file1);
664 sprintf(fname,"%s/digits_%d_%d.raw",fPath,fSlice,fPatch);
665 FILE *file2 = fopen(fname,"r");
668 cerr<<"AliL3Compress::PrintCompRatio(): Error opening file: "<<fname<<endl;
671 fseek(file2,0,SEEK_END);
672 UInt_t filesize2 = (UInt_t)ftell(file2);
675 cout<<"----------------------"<<endl;
676 cout<<"Original file size : "<<filesize2<<endl;
677 cout<<"Compressed file size : "<<filesize1<<endl;
678 cout<<"Remaining digits : "<<digit_counter<<endl;
679 cout<<"Compression ratio : "<<(Float_t)(filesize1 + (10*digit_counter)/8)/(Float_t)(filesize2)<<endl;
683 void AliL3Compress::QSort(AliL3RandomDigitData **a, Int_t first, Int_t last)
686 // Sort array of AliL3RandomDigitData pointers using a quicksort algorithm.
687 // Uses CompareDigits() to compare objects.
690 static AliL3RandomDigitData *tmp;
691 static int i; // "static" to save stack space
694 while (last - first > 1) {
698 while (++i < last && CompareDigits(a[i], a[first]) < 0)
700 while (--j > first && CompareDigits(a[j], a[first]) > 0)
716 if (j - first < last - (j + 1)) {
718 first = j + 1; // QSort(j + 1, last);
720 QSort(a, j + 1, last);
721 last = j; // QSort(first, j);
726 void AliL3Compress::WriteRootFile(Char_t *newrootfile)
730 AliL3MemHandler *mem = new AliL3MemHandler();
731 sprintf(fname,"%s/comp/restored_%d_%d.raw",fPath,fSlice,fPatch);
732 mem->SetBinaryInput(fname);
734 AliL3DigitRowData *rowPt = (AliL3DigitRowData*)mem->CompBinary2Memory(ndigits);
735 mem->CloseBinaryInput();
737 sprintf(fname,"%s/digitfile.root",fPath);
739 AliL3FileHandler *file = new AliL3FileHandler();
740 if(!file->SetAliInput(fname))
742 cerr<<"AliL3Compress::WriteRootFile() : Error opening file: "<<fname<<endl;
746 file->Init(fSlice,fPatch);
747 file->AliDigits2RootFile(rowPt,newrootfile);
748 file->CloseAliInput();