3 // Author: Anders Vestbo <mailto:vestbo$fi.uib.no>
4 //*-- Copyright © ALICE HLT Group
5 //_____________________________________________________________
9 // Class for compressing and uncompressing data.
11 #include "AliL3StandardIncludes.h"
14 #include "AliL3RootTypes.h"
15 #include "AliL3Models.h"
16 #include "AliL3DigitData.h"
17 #include "AliL3Logging.h"
18 #include "AliL3TrackArray.h"
19 #include "AliL3ModelTrack.h"
20 #include "AliL3Transform.h"
21 #include "AliL3MemHandler.h"
22 #include "AliL3DataCompressorHelper.h"
23 #include "AliL3DataCompressor.h"
24 #include "AliL3SpacePointData.h"
33 #include "AliL3FileHandler.h"
37 #include "AliL3Compress.h"
44 ClassImp(AliL3Compress)
46 AliL3Compress::AliL3Compress()
48 // default constructor
56 AliL3Compress::AliL3Compress(Int_t slice,Int_t patch,Char_t *path,Bool_t writeshape,Int_t event)
63 sprintf(fPath,"%s",path);
64 fWriteShape=writeshape;
67 AliL3Compress::~AliL3Compress()
74 Bool_t AliL3Compress::WriteFile(AliL3TrackArray *tracks,Char_t *filename)
79 sprintf(fname,"%s/comp/%s",fPath,filename);
81 sprintf(fname,"%s/comp/tracks_m_%d_%d.raw",fPath,fSlice,fPatch);
83 sprintf(fname,"%s/comp/tracks_m_%d_%d_%d.raw",fPath,fEvent,fSlice,fPatch);
85 FILE *file = fopen(fname,"w");
88 cerr<<"AliL3Compress::WriteFile : Error opening file "<<fname<<endl;
91 Short_t ntracks = tracks->GetNTracks();
94 AliL3ClusterModel *clusters=0;
95 AliL3TrackModel *model=0;
96 for(Int_t i=0; i<ntracks; i++)
98 AliL3ModelTrack *track = (AliL3ModelTrack*)tracks->GetCheckedTrack(i);
101 //Do not save useless tracks or clusters:
102 //if(track->GetNPresentClusters() == 0)
106 model = track->GetModel();
107 //if(model->fNClusters==0) continue;
108 clusters = track->GetClusters();
109 if(fwrite(model,sizeof(AliL3TrackModel),1,file)!=1) break;
110 //if(fwrite(clusters,model->fNClusters*sizeof(AliL3ClusterModel),1,file)!=1) break;
111 if(fwrite(clusters,AliL3Transform::GetNRows(fPatch)*sizeof(AliL3ClusterModel),1,file)!=1) break;
119 Bool_t AliL3Compress::ReadFile(Char_t which,Char_t *filename)
121 //Read the trackfile.
125 sprintf(fname,"%s/comp/%s",fPath,filename);
131 sprintf(fname,"%s/comp/tracks_m_%d_%d.raw",fPath,fSlice,fPatch);
133 sprintf(fname,"%s/comp/tracks_m_%d_%d_%d.raw",fPath,fEvent,fSlice,fPatch);
135 else if(which == 'u')
138 sprintf(fname,"%s/comp/tracks_u_%d_%d.raw",fPath,fSlice,fPatch);
140 sprintf(fname,"%s/comp/tracks_u_%d_%d_%d.raw",fPath,fEvent,fSlice,fPatch);
144 cerr<<"AliL3Compress::ReadFile() : Wrong option"<<endl;
149 FILE *file = fopen(fname,"r");
152 cerr<<"AliL3Compress::ReadFile : Cannot open file "<<fname<<endl;
158 fTracks = new AliL3TrackArray("AliL3ModelTrack");
162 AliL3ModelTrack *track = (AliL3ModelTrack*)fTracks->NextTrack();
163 track->Init(fSlice,fPatch);
164 AliL3TrackModel *model = track->GetModel();
165 AliL3ClusterModel *clusters = track->GetClusters();
166 if(fread(model,sizeof(AliL3TrackModel),1,file)!=1) break;
167 //if(fread(clusters,model->fNClusters*sizeof(AliL3ClusterModel),1,file)!=1) break;
168 if(fread(clusters,AliL3Transform::GetNRows(fPatch)*sizeof(AliL3ClusterModel),1,file)!=1) break;
172 fTracks->RemoveLast();
177 Bool_t AliL3Compress::CompressFile()
182 sprintf(fname,"%s/comp/tracks_c_%d_%d.raw",fPath,fSlice,fPatch);
184 sprintf(fname,"%s/comp/tracks_c_%d_%d_%d.raw",fPath,fEvent,fSlice,fPatch);
185 BIT_FILE *output = OpenOutputBitFile(fname);
188 sprintf(fname,"%s/comp/tracks_m_%d_%d.raw",fPath,fSlice,fPatch);
190 sprintf(fname,"%s/comp/tracks_m_%d_%d_%d.raw",fPath,fEvent,fSlice,fPatch);
192 FILE *input = fopen(fname,"r");
195 cerr<<"AliL3Compress::CompressFile() : Error opening file: "<<fname<<endl;
199 AliL3TrackModel track;
200 AliL3ClusterModel cluster;
204 Int_t timeo,pado,chargeo,padshapeo,timeshapeo;
205 timeo=pado=chargeo=padshapeo=timeshapeo=0;
208 if(fread(&track,sizeof(AliL3TrackModel),1,input)!=1) break;
210 if(output->mask != 0x80) //Write the current byte to file.
212 //cerr<<"\nAliL3Compress::CompressFile() : Writing overhead bits!!!"<<endl;
213 if(putc(output->rack,output->file )!=output->rack)
214 cerr<<"AliL3Compress::ComressFile : Error writing to bitfile"<<endl;
219 //Write track parameters:
220 fwrite(&track,sizeof(AliL3TrackModel),1,output->file);
222 Int_t origslice=-1,slice,clustercount=0;
223 for(Int_t i=0; i<AliL3Transform::GetNRows(fPatch); i++)
225 if(fread(&cluster,sizeof(AliL3ClusterModel),1,input)!=1) break;
228 temp = (Int_t)cluster.fPresent;
229 OutputBit(output,temp);
232 if(cluster.fSlice<0 || cluster.fSlice>35)
234 cerr<<"AliL3DataCompress::CompressFile : Fucked up slice number :"<<cluster.fSlice<<endl;
238 //Write slice number of first point
241 origslice = cluster.fSlice;
242 OutputBits(output,origslice,6); //Need 6 bits to encode slice number
246 slice = cluster.fSlice;
247 if(slice == origslice)
248 OutputBit(output,0); //No change of slice
252 OutputBits(output,slice,6);
257 //Write time information:
258 temp = (Int_t)rint(cluster.fDTime);
263 power = 1<<(AliL3DataCompressorHelper::GetNTimeBits()-1);
266 //cout<<abs(temp)<<" "<<power<<endl;
270 OutputBits(output,abs(temp),(AliL3DataCompressorHelper::GetNTimeBits()-1));
272 //Write pad information:
273 temp = (Int_t)rint(cluster.fDPad);
278 power = 1<<(AliL3DataCompressorHelper::GetNPadBits()-1);
284 OutputBits(output,abs(temp),(AliL3DataCompressorHelper::GetNPadBits()-1));
286 //Write charge information:
287 temp = (Int_t)cluster.fDCharge;
288 power = 1<<(AliL3DataCompressorHelper::GetNChargeBits());
294 OutputBits(output,abs(temp),(AliL3DataCompressorHelper::GetNChargeBits()));
298 //Write shape information:
299 temp = (Int_t)rint(cluster.fDSigmaY);
304 power = 1<<(AliL3DataCompressorHelper::GetNShapeBits()-1);
305 if(abs(temp) >= power)
310 OutputBits(output,abs(temp),(AliL3DataCompressorHelper::GetNShapeBits()-1));
312 temp = (Int_t)rint(cluster.fDSigmaZ);
317 power = 1<<(AliL3DataCompressorHelper::GetNShapeBits()-1);
318 if(abs(temp) >= power)
323 OutputBits(output,abs(temp),(AliL3DataCompressorHelper::GetNShapeBits()-1));
331 CloseOutputBitFile(output);
332 if(pado || timeo || chargeo || padshapeo || timeshapeo)
334 cout<<endl<<"Saturations: "<<endl
336 <<"Time "<<timeo<<endl
337 <<"Charge "<<chargeo<<endl
338 <<"Padshape "<<padshapeo<<endl
339 <<"Timeshape "<<timeshapeo<<endl<<endl;
344 Bool_t AliL3Compress::ExpandFile()
349 sprintf(fname,"%s/comp/tracks_c_%d_%d.raw",fPath,fSlice,fPatch);
351 sprintf(fname,"%s/comp/tracks_c_%d_%d_%d.raw",fPath,fEvent,fSlice,fPatch);
352 BIT_FILE *input = OpenInputBitFile(fname);
355 sprintf(fname,"%s/comp/tracks_u_%d_%d.raw",fPath,fSlice,fPatch);
357 sprintf(fname,"%s/comp/tracks_u_%d_%d_%d.raw",fPath,fEvent,fSlice,fPatch);
358 FILE *output = fopen(fname,"w");
361 cerr<<"AliL3Compress::ExpandFile() : Error opening file: "<<fname<<endl;
365 AliL3TrackModel trackmodel;
366 AliL3ClusterModel *clusters=0;
369 clusters = new AliL3ClusterModel[(AliL3Transform::GetNRows(fPatch))];
370 while(!feof(input->file))
372 input->mask=0x80;//make sure we read a new byte from file.
374 //Read and write track:
375 if(fread(&trackmodel,sizeof(AliL3TrackModel),1,input->file)!=1) break;
376 fwrite(&trackmodel,sizeof(AliL3TrackModel),1,output);
378 memset(clusters,0,AliL3Transform::GetNRows(fPatch)*sizeof(AliL3ClusterModel));
379 Int_t origslice=-1,clustercount=0;
380 for(Int_t i=0; i<AliL3Transform::GetNRows(fPatch); i++)
385 temp = InputBit(input);
388 clusters[i].fPresent=kFALSE;
391 clusters[i].fPresent=kTRUE;
393 //Read slice information
396 temp = InputBits(input,6);
397 clusters[i].fSlice = temp;
402 temp = InputBit(input);
404 clusters[i].fSlice = origslice;
407 temp = InputBits(input,6);//read new slice
408 clusters[i].fSlice = temp;
409 origslice = temp;//store new slice
413 //Read time information:
414 sign=InputBit(input);
415 temp = InputBits(input,(AliL3DataCompressorHelper::GetNTimeBits()-1));
418 clusters[i].fDTime = temp;
420 //Read pad information:
421 sign=InputBit(input);
422 temp = InputBits(input,(AliL3DataCompressorHelper::GetNPadBits()-1));
425 clusters[i].fDPad = temp;
427 //Read charge information:
428 temp=InputBits(input,(AliL3DataCompressorHelper::GetNChargeBits()));
429 clusters[i].fDCharge = temp;
433 //Read shape information:
434 sign = InputBit(input);
435 temp = InputBits(input,(AliL3DataCompressorHelper::GetNShapeBits()-1));
438 clusters[i].fDSigmaY = temp;
440 sign = InputBit(input);
441 temp = InputBits(input,(AliL3DataCompressorHelper::GetNShapeBits()-1));
444 clusters[i].fDSigmaZ = temp;
449 //fwrite(clusters,(trackmodel.fNClusters)*sizeof(AliL3ClusterModel),1,output);
450 fwrite(clusters,AliL3Transform::GetNRows(fPatch)*sizeof(AliL3ClusterModel),1,output);
455 CloseInputBitFile(input);
459 void AliL3Compress::CompressRemaining(AliL3SpacePointData *clusters[36][6],UInt_t nclusters[36][6])
461 //Write the remaining clusters in a compressed format.
463 Char_t filename[1024];
464 Int_t nrows = AliL3Transform::GetNRows();
465 Int_t *npoints = new Int_t[nrows];
466 for(Int_t slice=0; slice<=35; slice++)
468 for(Int_t patch=0; patch < 1; patch++)
470 sprintf(filename,"%s/comp/remains_%d_%d_%d.raw",fPath,fEvent,slice,-1);
471 BIT_FILE *output = OpenOutputBitFile(filename);
474 cerr<<"AliL3Compress::CompressRemaining : Cannot open file "<<filename<<endl;
477 AliL3SpacePointData *cl = clusters[slice][patch];
478 memset(npoints,0,nrows*sizeof(Int_t));
481 for(i=0; i<nclusters[slice][patch]; i++)
483 if(cl[i].fCharge == 0) continue; //has been used
484 npoints[cl[i].fPadRow]++;
487 for(Int_t j=0; j<nrows; j++)
489 if(!npoints[j]) continue;
493 //Write number of padrows with clusters
494 OutputBits(output,rowspresent,8);
497 for(i=0; i<nclusters[slice][patch]; i++)
499 if(cl[i].fCharge == 0) continue; //has been used
500 Int_t padrow = cl[i].fPadRow;
501 if(padrow != lastPadrow)
503 OutputBits(output,padrow,8);//Write padrow #
504 if(npoints[padrow] >= 1<<10)
506 cerr<<"AliL3Compress::CompressRemaining : Too many remaining clusters "<<npoints[padrow]<<endl;
509 OutputBits(output,npoints[padrow],10);//Write number of clusters on this padrow
513 Float_t xyz[3] = {cl[i].fX,cl[i].fY,cl[i].fZ};
514 Int_t sector,row,buff;
515 AliL3Transform::Slice2Sector(slice,padrow,sector,row);
516 AliL3Transform::Global2Raw(xyz,sector,row);
518 Float_t padw = sqrt(cl[i].fSigmaY2) / AliL3Transform::GetPadPitchWidth(AliL3Transform::GetPatch(padrow));
519 Float_t timew = sqrt(cl[i].fSigmaZ2) / AliL3Transform::GetZWidth();
521 //Check for saturation in the widths.
522 //Basically only store a certain number of decimals here, and cut the widths which is higher:
523 if(padw >= (1<<AliL3DataCompressorHelper::GetNShapeBitsRemaining()) / AliL3DataCompressorHelper::GetPadPrecisionFactor())
524 padw = (1<<AliL3DataCompressorHelper::GetNShapeBitsRemaining()) / AliL3DataCompressorHelper::GetPadPrecisionFactor() - 1/AliL3DataCompressorHelper::GetPadPrecisionFactor();
525 if(timew >= (1<<AliL3DataCompressorHelper::GetNShapeBitsRemaining()) / AliL3DataCompressorHelper::GetTimePrecisionFactor())
526 timew = (1<<AliL3DataCompressorHelper::GetNShapeBitsRemaining()) / AliL3DataCompressorHelper::GetTimePrecisionFactor() - 1/AliL3DataCompressorHelper::GetTimePrecisionFactor();;
529 buff = (Int_t)rint(xyz[1]*AliL3DataCompressorHelper::GetPadPrecisionFactor());
532 cerr<<"AliL3Compress:CompressRemaining : Wrong pad value "<<buff<<endl;
535 OutputBits(output,buff,AliL3DataCompressorHelper::GetNPadBitsRemaining());
538 buff = (Int_t)rint(xyz[2]*AliL3DataCompressorHelper::GetTimePrecisionFactor());
541 cerr<<"AliL3Compress:CompressRemaining : Wrong time value "<<buff<<endl;
544 OutputBits(output,buff,AliL3DataCompressorHelper::GetNTimeBitsRemaining());
547 buff = (Int_t)rint(padw*AliL3DataCompressorHelper::GetPadPrecisionFactor());
548 OutputBits(output,buff,AliL3DataCompressorHelper::GetNShapeBitsRemaining());
549 buff = (Int_t)rint(timew*AliL3DataCompressorHelper::GetTimePrecisionFactor());
550 OutputBits(output,buff,AliL3DataCompressorHelper::GetNShapeBitsRemaining());
553 buff = cl[i].fCharge;
554 if(buff >= 1<<(AliL3DataCompressorHelper::GetNChargeBits()))
555 buff = (1<<(AliL3DataCompressorHelper::GetNChargeBits()))-1;
556 OutputBits(output,buff,AliL3DataCompressorHelper::GetNChargeBits());
559 CloseOutputBitFile(output);
566 void AliL3Compress::ExpandRemaining(TempCluster **clusters,Int_t *ncl, Int_t /*maxpoints*/)
568 //Expand the remaining clusters stored using function CompressRemaining
570 Char_t filename[1024];
572 for(Int_t slice=0; slice<=35; slice++)
574 for(Int_t p=0; p<1; p++)
576 sprintf(filename,"%s/comp/remains_%d_%d_%d.raw",fPath,fEvent,slice,-1);
577 BIT_FILE *input = OpenInputBitFile(filename);
579 //Read number of padrows
580 buff = InputBits(input,8);
583 for(Int_t i=0; i<nrows; i++)
586 buff = InputBits(input,8);
590 buff = InputBits(input,10);
591 Int_t npoints = buff;
593 for(Int_t i=0; i<npoints; i++)
595 clusters[slice][ncl[slice]].fPadrow = padrow;
598 buff = InputBits(input,AliL3DataCompressorHelper::GetNPadBitsRemaining());
599 clusters[slice][ncl[slice]].fPad = (Float_t)buff/AliL3DataCompressorHelper::GetPadPrecisionFactor();
602 buff = InputBits(input,AliL3DataCompressorHelper::GetNTimeBitsRemaining());
603 clusters[slice][ncl[slice]].fTime = (Float_t)buff/AliL3DataCompressorHelper::GetTimePrecisionFactor();
606 buff = InputBits(input,AliL3DataCompressorHelper::GetNShapeBitsRemaining());
607 clusters[slice][ncl[slice]].fSigmaY2 = pow((Float_t)buff/AliL3DataCompressorHelper::GetPadPrecisionFactor(),2);
608 buff = InputBits(input,AliL3DataCompressorHelper::GetNShapeBitsRemaining());
609 clusters[slice][ncl[slice]].fSigmaZ2 = pow((Float_t)buff/AliL3DataCompressorHelper::GetPadPrecisionFactor(),2);
612 buff = InputBits(input,AliL3DataCompressorHelper::GetNChargeBits());
613 clusters[slice][ncl[slice]].fCharge = buff;
619 CloseInputBitFile(input);
624 void AliL3Compress::PrintCompRatio(ofstream *outfile)
626 // prints the compression ratio
627 AliL3MemHandler *mem = new AliL3MemHandler();
629 UInt_t remainSize=0,digitSize=0;
630 for(Int_t i=0; i<36; i++)
633 sprintf(fname,"%s/comp/remains_%d_%d.raw",fPath,i,-1);
635 sprintf(fname,"%s/comp/remains_%d_%d_%d.raw",fPath,fEvent,i,-1);
636 mem->SetBinaryInput(fname);
637 remainSize += mem->GetFileSize();
638 mem->CloseBinaryInput();
640 sprintf(fname,"%s/binaries/digits_c8_%d_%d_%d.raw",fPath,fEvent,i,-1);
641 mem->SetBinaryInput(fname);
642 digitSize += mem->GetFileSize();
643 mem->CloseBinaryInput();
648 sprintf(fname,"%s/comp/tracks_c_%d_%d.raw",fPath,fSlice,fPatch);
650 sprintf(fname,"%s/comp/tracks_c_%d_%d_%d.raw",fPath,fEvent,fSlice,fPatch);
652 mem->SetBinaryInput(fname);
653 UInt_t compressSize = mem->GetFileSize();
654 mem->CloseBinaryInput();
658 cerr<<"AliL3Compress::PrintCompRatio : Zero digit size, not able to obtain comp. ratios!"<<endl;
662 Float_t compratio = (Float_t)(compressSize + remainSize)/(Float_t)digitSize;
664 Int_t trackSize = GetEntropy(entropy[0],entropy[1],entropy[2])*sizeof(AliL3TrackModel);
667 ofstream &out = *outfile;
668 out<<compressSize<<' '<<remainSize<<' '<<digitSize<<' '<<trackSize<<' '<<entropy[0]<<' '<<entropy[1]<<endl;
671 cout<<"=========================================="<<endl;
672 cout<<"Original digits size : "<<digitSize/1000<<" kByte ( 100 % )"<<endl;
673 cout<<"Compressed file size : "<<compressSize/1000<<" kByte ( "<<(Float_t)compressSize*100/(Float_t)digitSize<<" % )"<<endl;
674 cout<<"Remaining file size : "<<remainSize/1000<<" kByte ( "<<(Float_t)remainSize*100/(Float_t)digitSize<<" % )"<<endl;
675 cout<<"Relative track size : "<<trackSize/1000<<" kByte ( "<<(Float_t)trackSize*100/(Float_t)digitSize<<" % )"<<endl;
676 cout<<"Relative cluster size: "<<(compressSize-trackSize)/1000<<" kByte ( "<<(Float_t)(compressSize-trackSize)*100/(Float_t)digitSize<<" % )"<<endl;
677 cout<<"---------------------- "<<endl;
678 cout<<"Compression ratio : "<<compratio*100<<" %"<<endl;
679 cout<<"=========================================="<<endl;
680 cout<<"Entropy of residuals : "<<entropy[0]<<" "<<entropy[1]<<endl;
683 Int_t AliL3Compress::GetEntropy(Float_t &padEntropy,Float_t &timeEntropy,Float_t &chargeEntropy)
685 //Calculate the entropy of the quantized residuals in both directions
689 const Int_t knmax=100000;
691 Float_t times[knmax];
692 Float_t charge[knmax];
693 memset(&pads[0],0,knmax*sizeof(Float_t));
694 memset(×[0],0,knmax*sizeof(Float_t));
695 memset(&charge[0],0,knmax*sizeof(Float_t));
698 for(Int_t i=0; i<fTracks->GetNTracks(); i++)
700 AliL3ModelTrack *track = (AliL3ModelTrack*)fTracks->GetCheckedTrack(i);
702 for(Int_t padrow=0; padrow<AliL3Transform::GetNRows(); padrow++)
704 if(!track->IsPresent(padrow)) continue;
705 Int_t dpad = abs((Int_t)rint(track->GetClusterModel(padrow)->fDPad));
706 Int_t dtime = abs((Int_t)rint(track->GetClusterModel(padrow)->fDTime));
707 Int_t dcharge = (Int_t)track->GetClusterModel(padrow)->fDCharge;
708 if(dpad >= knmax || dtime >= knmax || dcharge >= knmax)
710 cerr<<"AliL3Compress::GetEntropy : Quantization out of range: "<<dpad<<" "<<dtime<<" "<<dcharge<<endl;
719 padEntropy=timeEntropy=chargeEntropy=0;
720 for(Int_t i=0; i<knmax; i++)
723 padEntropy += (pads[i]/counter)*(log(pads[i]/counter)/log(2.0));
725 timeEntropy += (times[i]/counter)*(log(times[i]/counter)/log(2.0));
727 chargeEntropy += (charge[i]/counter)*(log(charge[i]/counter)/log(2.0));
733 return fTracks->GetNTracks();