// @(#) $Id$ // Author: Anders Vestbo //*-- Copyright © ALICE HLT Group //_____________________________________________________________ // // AliL3CompressAC // // Compression class which performs Arithmetic Coding of the quantized residuals. // The implemented algorithm is inspired by the examples in The Data Compression Book // by Nelson & Gailly. #if __GNUC__ >= 3 using namespace std; #endif #include "AliL3StandardIncludes.h" #include "AliL3TrackArray.h" #include "AliL3ModelTrack.h" #include "AliL3Transform.h" #include "AliL3MemHandler.h" #include "AliL3Compress.h" #include "AliL3DataCompressorHelper.h" #include "AliL3CompressAC.h" ClassImp(AliL3CompressAC) AliL3CompressAC::AliL3CompressAC() { // default constructor fCount=0; fTotals=0; fMax=0; fRange=0; fLow=0; fHigh=0; fUnderflowBits=0; fCode=0; } AliL3CompressAC::AliL3CompressAC(Int_t slice,Int_t patch,Char_t *path,Bool_t writeshape,Int_t event) : AliL3Compress(slice,patch,path,writeshape,event) { // constructor fCount=0; fTotals=0; fMax=0; fRange=0; fLow=0; fHigh=0; fUnderflowBits=0; fCode=0; } AliL3CompressAC::~AliL3CompressAC() { // destructor ClearArrays(); } void AliL3CompressAC::ClearArrays() { // cleans all arrays fMax=0; if(fCount) delete [] fCount; if(fTotals) delete [] fTotals; } void AliL3CompressAC::BuildModel(BIT_FILE *output) { //Build the model from the input data, i.e. probability distributions of the quantized residuals. ClearArrays(); ReadFile('m'); UInt_t nmax=10000,qres; UInt_t * temp = new UInt_t[nmax]; memset(&temp[0],0,nmax*sizeof(UInt_t)); AliL3TrackArray *tracks = GetTracks(); for(Int_t t=0; tGetNTracks(); t++) { AliL3ModelTrack *track = (AliL3ModelTrack*)tracks->GetCheckedTrack(t); if(!track) continue; for(Int_t padrow=0; padrowIsPresent(padrow)) continue; qres = abs((Int_t)rint(track->GetClusterModel(padrow)->fDPad)); if(qres >= nmax) { cerr<<"AliL3CompressAC::BuildModel() : Residual values seems way too big!"< fMax) fMax=qres; temp[qres]++; qres = abs((Int_t)rint(track->GetClusterModel(padrow)->fDTime)); if(qres > fMax) fMax = qres; temp[qres]++; } } fCount = new UChar_t[fMax+1]; //Find the highest counts in order to do scaling: UInt_t i,maxCount=0; for(i=0; i<=fMax; i++) { if(temp[i] > maxCount) maxCount=temp[i]; } //Perform the scaling UInt_t scale,total=1; scale = maxCount / 256 + 1; for(i=0; i<=fMax; i++) { fCount[i] = (UChar_t)(temp[i]/scale); if(fCount[i]==0 && temp[i]!=0) fCount[i] = 1; total += (UInt_t)fCount[i]; } if(total > (32767 - 256)) scale=4; else if(total > 16383) scale=2; else scale=1; if(scale > 1) for(i=0; i<=fMax; i++) fCount[i] /= scale; cout<<"Writing "<file); fwrite(fCount,sizeof(UChar_t),fMax+1,output->file); FillTotals(); delete [] temp; } void AliL3CompressAC::RebuildModel(BIT_FILE *input) { //Rebuild the model from the counts written to the beginning of the compressed file. ClearArrays(); fread(&fMax,sizeof(UShort_t),1,input->file); fCount = new UChar_t[fMax+1]; fread(fCount,sizeof(UChar_t),fMax+1,input->file); FillTotals(); } void AliL3CompressAC::FillTotals() { //Fill the array of totals, which is actually the model being used during encoding/decoding. if(fMax == 0) cerr<<"AliL3CompressAC::FillTotals : max value is zero!"< 0) { OutputBit(output,~fHigh & 0x8000); fUnderflowBits--; } } else if( (fLow & 0x4000) && !(fHigh & 0x4000) ) { fUnderflowBits++; fLow &= 0x3fff; fHigh |= 0x4000; } else return; fLow <<= 1; fHigh <<= 1; fHigh |= 1; } } void AliL3CompressAC::RemoveSymbolFromStream(BIT_FILE *input,Int_t j) { // remves symbol fro stream UInt_t range = (UInt_t)(fHigh-fLow)+1; fHigh = fLow + (UShort_t)((range*fTotals[j+1])/fTotals[fMax+2]-1); fLow = fLow + (UShort_t)((range*fTotals[j])/fTotals[fMax+2]); while(1) { if( (fHigh & 0x8000)==(fLow & 0x8000) ) {} else if((fLow & 0x4000) == 0x4000 && (fHigh & 0x4000)==0) { fCode ^= 0x4000; fLow &= 0x3fff; fHigh |= 0x4000; } else return; fLow <<= 1; fHigh <<= 1; fHigh |= 1; fCode <<= 1; fCode += InputBit(input); } } void AliL3CompressAC::FlushEncoder(BIT_FILE *output) { //Flush the encoder: OutputBit(output,fLow & 0x4000); fUnderflowBits++; while(fUnderflowBits-- > 0) OutputBit(output,~fLow & 0x4000); } Bool_t AliL3CompressAC::CompressFile() { // comresses file Char_t fname[100]; if(fEvent<0) sprintf(fname,"%s/comp/tracks_ac_%d_%d.raw",fPath,fSlice,fPatch); else sprintf(fname,"%s/comp/tracks_ac_%d_%d_%d.raw",fPath,fEvent,fSlice,fPatch); BIT_FILE *output = OpenOutputBitFile(fname); if(fEvent<0) sprintf(fname,"%s/comp/tracks_m_%d_%d.raw",fPath,fSlice,fPatch); else sprintf(fname,"%s/comp/tracks_m_%d_%d_%d.raw",fPath,fEvent,fSlice,fPatch); FILE *input = fopen(fname,"r"); if(!input) { cerr<<"AliL3CompressAC::CompressFileAC() : Error opening file: "<file); AliL3ClusterModel **clusters = new AliL3ClusterModel*[trackcount]; Int_t *clustercount = new Int_t[trackcount]; i=0; //Read all the tracks from input file, and write them all to the outputfile. //Store the clusters in memory for later encoding and storing. while(!feof(input)) { if(fread(&track,sizeof(AliL3TrackModel),1,input)!=1) break; fwrite(&track,sizeof(AliL3TrackModel),1,output->file); clusters[i] = new AliL3ClusterModel[AliL3Transform::GetNRows()]; clustercount[i]=0; //Read in the clusters: fread(clusters[i],sizeof(AliL3ClusterModel),AliL3Transform::GetNRows(fPatch),input); i++; } if(i != trackcount) { cerr<<"AliL3CompressAC::CompressFile : Mismatching file size and trackcount "<35) { cerr<<"AliL3DataCompress::CompressFile : Fucked up slice number :"< origslice) OutputBit(output,1); else OutputBit(output,0); } else { if( (slice == 0 && origslice == 17) || (slice == 18 && origslice == 35) ) OutputBit(output,1); else if( (slice == 17 && origslice == 0) || (slice == 35 && origslice == 18) ) OutputBit(output,0); } origslice=slice; } } //Write charge information: temp = (Int_t)clusters[i][j].fDCharge; power = 1<<(AliL3DataCompressorHelper::GetNChargeBits()); if(abs(temp)>=power) { temp=power - 1; } OutputBits(output,abs(temp),(AliL3DataCompressorHelper::GetNChargeBits())); //Write sign information of the residuals: temp = (Int_t)rint(clusters[i][j].fDTime); if(temp<0) OutputBit(output,0); else OutputBit(output,1); temp = (Int_t)rint(clusters[i][j].fDPad); if(temp<0) OutputBit(output,0); else OutputBit(output,1); //Write shape information if requested: if(fWriteShape) { temp = (Int_t)rint(clusters[i][j].fDSigmaY); if(temp<0) OutputBit(output,0); else OutputBit(output,1); power = 1<<(AliL3DataCompressorHelper::GetNShapeBits()-1); if(abs(temp) >= power) { temp = power - 1; } OutputBits(output,abs(temp),(AliL3DataCompressorHelper::GetNShapeBits()-1)); temp = (Int_t)rint(clusters[i][j].fDSigmaZ); if(temp<0) OutputBit(output,0); else OutputBit(output,1); power = 1<<(AliL3DataCompressorHelper::GetNShapeBits()-1); if(abs(temp) >= power) { temp=power - 1; } OutputBits(output,abs(temp),(AliL3DataCompressorHelper::GetNShapeBits()-1)); } clustercount[i]++; } } InitEncoder(); //Start the arithmetic coding of the residuals. //All the residuals (both pad and time) are coded in one go, //i.e. for all tracks and clusters in the input file. for(i=0; ifile); AliL3TrackModel *trackmodels = new AliL3TrackModel[trackcount]; AliL3ClusterModel **clusters = new AliL3ClusterModel*[trackcount]; Int_t *clustercount = new Int_t[trackcount]; fread(trackmodels,sizeof(AliL3TrackModel),trackcount,input->file); for(i=0; i 35) { cerr<<"AliL3CompressAC::ExpandFile : Bad slice number "<SetBinaryInput(fname); remainSize += mem->GetFileSize(); mem->CloseBinaryInput(); sprintf(fname,"%s/binaries/digits_c8_%d_%d_%d.raw",fPath,fEvent,i,-1); mem->SetBinaryInput(fname); digitSize += mem->GetFileSize(); mem->CloseBinaryInput(); } if(fEvent<0) sprintf(fname,"%s/comp/tracks_ac_%d_%d.raw",fPath,fSlice,fPatch); else sprintf(fname,"%s/comp/tracks_ac_%d_%d_%d.raw",fPath,fEvent,fSlice,fPatch); mem->SetBinaryInput(fname); UInt_t compressSize = mem->GetFileSize(); mem->CloseBinaryInput(); if(digitSize==0) { cerr<<"AliL3Compress::PrintCompRatio : Zero digit size, not able to obtain comp. ratios!"<