/************************************************************************** * Copyright(c) 1998-2003, ALICE Experiment at CERN, All rights reserved. * * * * Author: The ALICE Off-line Project. * * Contributors are mentioned in the code where appropriate. * * * * Permission to use, copy, modify and distribute this software and its * * documentation strictly for non-commercial purposes is hereby granted * * without fee, provided that the above copyright notice appears in all * * copies and that both the copyright notice and this permission notice * * appear in the supporting documentation. The authors make no claims * * about the suitability of this software for any purpose. It is * * provided "as is" without express or implied warranty. * **************************************************************************/ #include #include "Riostream.h" #include "TMath.h" #include "AliTPCCompression.h" #include "AliTPCBuffer160.h" #include "AliTPCHuffman.h" ClassImp(AliTPCCompression) ////////////////////////////////////////////////////////////////////////////////////////////////// AliTPCCompression::AliTPCCompression(){ fDimBuffer=sizeof(ULong_t)*8; fFreeBitsBuffer=fDimBuffer; fReadBits=0; fPos=0; fBuffer=0; fVerbose=0; fFillWords=0; return; } ////////////////////////////////////////////////////////////////////////////////////////////////// AliTPCCompression::AliTPCCompression(const AliTPCCompression &source){ this->fDimBuffer=source.fDimBuffer; this->fFreeBitsBuffer=source.fFreeBitsBuffer; this->fReadBits=source.fReadBits; this->fPos=source.fPos; this->fBuffer=source.fBuffer; this->fVerbose=source.fVerbose; this->fFillWords=source.fFillWords; return; } ////////////////////////////////////////////////////////////////////////////////////////////////// AliTPCCompression& AliTPCCompression::operator=(const AliTPCCompression &source){ this->fDimBuffer=source.fDimBuffer; this->fFreeBitsBuffer=source.fFreeBitsBuffer; this->fReadBits=source.fReadBits; this->fPos=source.fPos; this->fBuffer=source.fBuffer; this->fVerbose=source.fVerbose; this->fFillWords=source.fFillWords; return *this; } ////////////////////////////////////////////////////////////////////////////////////////////////// void AliTPCCompression::NextTable(Int_t Val,Int_t &NextTableType,Int_t &BunchLen,Int_t &Count){ /* Table index: 0==> Bunch length value 1==> Time Bin value 2==> 1-samples bunch 3==> Central samples 4==> Border samples */ switch (NextTableType){ case 0:{ BunchLen=Val-2; NextTableType=1; break; }//end case 0 case 1:{ if (BunchLen==1)NextTableType=2; else{ NextTableType=4; Count=1; } break; }//end case 1 case 2:{ NextTableType=0; break; }//end case 2 case 3:{ Count++; if (Count==(BunchLen-1)){ NextTableType=4; } break; }//end case 3 case 4:{ if (Count==1){ if (BunchLen>2) NextTableType=3; else Count++; } else NextTableType=0; break; }//end case 4 }//end switch return; } ///////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////// Int_t AliTPCCompression::FillTables(const char* fSource,AliTPCHTable* table[],const Int_t NumTables){ //This method is used to compute the frequencies of the symbols in the source file AliTPCBuffer160 Buff(fSource,0); ULong_t CountWords=0; ULong_t CountTrailer=0; Int_t NumWords,PadNum,RowNum,SecNum=0; Int_t Value=0; ULong_t Stat[5]={0,0,0,0,0}; Int_t EndFill=0; Int_t End=1; while(Buff.ReadTrailerBackward(NumWords,PadNum,RowNum,SecNum) !=-1 ){ if(End){ EndFill=Buff.GetFillWordsNum(); End=0; }//endif CountTrailer++; if (NumWords%4){ fFillWords+=4-NumWords%4; for(Int_t j=0;j<(4-NumWords%4);j++){ Value=Buff.GetNextBackWord(); }//end for }//end if Int_t Packet[1024]; Int_t TimePos[345]; Int_t Tp=0; for(Int_t i=0;i<345;i++)TimePos[i]=0; for(Int_t i=0;i<1024;i++)Packet[i]=0; Int_t NextTableType=0; Int_t BunchLen=0; Int_t Count=0; for(Int_t i=0;i=0;i--){ Int_t TimPos=TimePos[i]; Int_t BunchLen=Packet[TimPos-1]-2; temp=Packet[TimPos]; Packet[TimPos]=Packet[TimPos]-PreviousTime-BunchLen; PreviousTime=temp; } NextTableType=0; Count=0; BunchLen=0; for(Int_t i=0;iSetFrequency(Value); Stat[NextTableType]++; NextTable(Value,NextTableType,BunchLen,Count); CountWords++; }//end for }//end while cout<<"Number of words: "<Size(); //Table dimension is written into a file fTable.write((char*)(&dim),sizeof(Int_t)); //One table is written into a file for(Int_t i=0;iCodeLen()[i]; // ULong_t Code=(ULong_t)table[k]->Code()[i]; Double_t Code=table[k]->Code()[i]; fTable.write((char*)(&CodeLen),sizeof(UChar_t)); //fTable.write((char*)(&Code),sizeof(ULong_t)); fTable.write((char*)(&Code),sizeof(Double_t)); } //end for fTable.close(); }//end for return 0; } //////////////////////////////////////////////////////////////////////////////////////// Int_t AliTPCCompression::CreateTables(const char* fSource,const Int_t NumTables){ Int_t n=10;// 10 bits per symbol /* Table index: 0==> Bunch length values 1==> Time Bin values 2==> 1-samples bunch 3==> Central samples 4==> Border samples */ AliTPCHTable ** table = new AliTPCHTable*[NumTables]; //The table is inizialized with the rigth number of rows for(Int_t i=0;iCompleteTable(i); } */ if(fVerbose){ cout<<"Entropy of Bunch length table........."<GetEntropy()<GetEntropy()<GetEntropy()<GetEntropy()<GetEntropy()<GetEntropy()<GetEntropy()<GetEntropy()<GetEntropy()<GetEntropy()<StoreFrequencies("BunchLenFreq.txt"); table[1]->StoreFrequencies("TimeFreq.txt"); table[2]->StoreFrequencies("Sample1Freq.txt"); table[3]->StoreFrequencies("SCentralFreq.txt"); table[4]->StoreFrequencies("SBorderFreq.txt"); if (fVerbose) cout<<"Creating Tables..\n"; //One Huffman tree is created for each table starting from the frequencies of the symbols for(Int_t i=0;iBuildHTable(); if (fVerbose==2){ cout<<"Number of elements inside the table:"<GetWordsNumber(); switch(i){ case 0:{ cout<<" (Bunch Length)"<PrintTable(); } } //The tables are saved ad binary files StoreTables(table,NumTables); //The tables stored in memory are deleted; for(Int_t i=0;iSetCodeLen(CodeLen,i); // fTable.read((char*)(&Code),sizeof(ULong_t)); fTable.read((char*)(&Code),sizeof(Double_t)); table[k]->SetCode(Mirror((ULong_t)Code,CodeLen),i); }//end for fTable.close(); }//end for if (fVerbose) cout<<"Trees generated \n"; //At this point the trees are been built return 0; } //////////////////////////////////////////////////////////////////////////////////////// /* COMPRESSION */ //////////////////////////////////////////////////////////////////////////////////////// void AliTPCCompression::StoreValue(ULong_t val,UChar_t len){ if (len<=fFreeBitsBuffer){ // val is not splitted in two buffer fFreeBitsBuffer-=len; fBuffer=fBuffer<>(len-fFreeBitsBuffer); fBuffer=fBuffer|temp; f.write((char*)(&fBuffer),sizeof(ULong_t)); fFreeBitsBuffer=fDimBuffer-(len-fFreeBitsBuffer); val=val<>fFreeBitsBuffer; fBuffer=val; }//end else return; } ////////////////////////////////////////////////////////////////////////////////////////////////// void AliTPCCompression::Flush(){ //The last buffen cannot be completely full if(fFreeBitsBuffer>i; specular=specular<<1; specular=specular|bit; Mask=Mask<<1; } return specular; } ////////////////////////////////////////////////////////////////////////////////////////////////// Int_t AliTPCCompression::CompressData(AliTPCHTable* table[],Int_t NumTable,const char* fSource,const char* fDest){ cout<<" COMPRESSION "<Size(); //Table dimension is written into a file f.write((char*)(&dim),sizeof(Int_t)); //One table is written into a file for(Int_t i=0;iCodeLen()[i]; ULong_t Code=(ULong_t)table[k]->Code()[i]; f.write((char*)(&CodeLen),sizeof(UChar_t)); f.write((char*)(&Code),sizeof(ULong_t)); } //end for }//end for // Source file is open AliTPCBuffer160 Buff(fSource,0); //coded words are written into the output file Int_t NumWords,PadNum,RowNum,SecNum=0; ULong_t StoredWords=0; Int_t Value=0; ULong_t NumPacket=0; while(Buff.ReadTrailerBackward(NumWords,PadNum,RowNum,SecNum) !=-1 ){ NumPacket++; if (NumWords%4){ for(Int_t j=0;j<(4-NumWords%4);j++){ Value=Buff.GetNextBackWord(); }//end for }//end if Int_t Packet[1024]; Int_t TimePos[345]; Int_t Tp=0; for(Int_t i=0;i<345;i++)TimePos[i]=0; for(Int_t i=0;i<1024;i++)Packet[i]=0; Int_t NextTableType=0; Int_t BunchLen=0; Int_t Count=0; for(Int_t i=0;i=0;i--){ Int_t TimPos=TimePos[i]; Int_t BunchLen=Packet[TimPos-1]-2; temp=Packet[TimPos]; Packet[TimPos]=Packet[TimPos]-PreviousTime-BunchLen; PreviousTime=temp; }//end for NextTableType=0; Count=0; BunchLen=0; Int_t TimeBin=0; //All the words for one pad are compressed and stored in the compress file for(Int_t i=0;i1){ // ULong_t val=(ULong_t)table[NextTableType]->Code()[Value]; // val is the code Double_t val=table[NextTableType]->Code()[Value]; // val is the code UChar_t len=table[NextTableType]->CodeLen()[Value]; // len is the length (number of bits)of val StoreValue(Mirror((ULong_t)val,len),len); StoredWords++; }//end if NextTable(Value,NextTableType,BunchLen,Count); if(NextTableType==0){ // ULong_t val=(ULong_t)table[1]->Code()[TimeBin]; // val is the code Double_t val=table[1]->Code()[TimeBin]; // val is the code UChar_t len=table[1]->CodeLen()[TimeBin]; // len is the length (number of bits)of val StoreValue(Mirror((ULong_t)val,len),len); //val=(ULong_t)table[NextTableType]->Code()[(BunchLen+2)]; // val is the code val=table[NextTableType]->Code()[(BunchLen+2)]; // val is the code len=table[NextTableType]->CodeLen()[(BunchLen+2)]; // len is the length (number of bits)of val StoreValue(Mirror((ULong_t)val,len),len); StoredWords+=2; } }//end for //Trailer StoreValue(NumWords,10); StoreValue(PadNum,10); StoreValue(RowNum,10); StoreValue(SecNum,9); StoreValue(1,1); StoredWords+=4; }//end while StoreValue(NumPacket,32); cout<<"Number of strored packet: "<=0;i--){ Int_t TimPos=TimePos[i]; Int_t BunchLen=Packet[TimPos-1]-2; temp=Packet[TimPos]; Packet[TimPos]=Packet[TimPos]-PreviousTime-BunchLen; PreviousTime=temp; }//end for NextTableType=0; Count=0; BunchLen=0; Int_t TimeBin=0; for(Int_t i=0;i1){ //ULong_t val=(ULong_t)table[NextTableType]->Code()[Value]; // val is the code Double_t val=table[NextTableType]->Code()[Value]; // val is the code UChar_t len=table[NextTableType]->CodeLen()[Value]; // len is the length (number of bits)of val Stat[NextTableType]+=len; NumElem[NextTableType]++; StoreValue((ULong_t)val,len); StoredWords++; }//end if NextTable(Value,NextTableType,BunchLen,Count); if(NextTableType==0){ // ULong_t val=(ULong_t)table[1]->Code()[TimeBin]; // val is the code Double_t val=table[1]->Code()[TimeBin]; // val is the code UChar_t len=table[1]->CodeLen()[TimeBin]; // len is the length (number of bits)of val Stat[1]+=len; NumElem[1]++; StoreValue((ULong_t)val,len); // val=(ULong_t)table[NextTableType]->Code()[(BunchLen+2)]; // val is the code val=table[NextTableType]->Code()[(BunchLen+2)]; // val is the code len=table[NextTableType]->CodeLen()[(BunchLen+2)]; // len is the length (number of bits)of val StoreValue((ULong_t)val,len); Stat[NextTableType]+=len; NumElem[NextTableType]++; StoredWords+=2; } }//end for //Trailer StoreValue(NumWords,10); StoreValue(PadNum,10); StoreValue(RowNum,10); StoreValue(SecNum,9); StoreValue(1,1); StoredWords+=4; TrailerNumber++; }//end while StoreValue(NumPacket,32); if(fVerbose) cout<<"Number of strored packet: "<GetRight(); if(!node){ node=new AliTPCHNode(); temp->SetRight(node); }//end if }//end if else{ node=node->GetLeft(); if(!node){ node=new AliTPCHNode(); temp->SetLeft(node); }//end if }//end else }//end for if(CodeLen){ node->SetSymbol(i); node->SetFrequency(CodeLen); }//end if //cout<GetSymbol()<<" "<<(Int_t)node->GetFrequency()<GetRight(); if(!node){ node=new AliTPCHNode(); temp->SetRight(node); }//end if }//end if else{ node=node->GetLeft(); if(!node){ node=new AliTPCHNode(); temp->SetLeft(node); }//end if }//end else }//end for if(CodeLen){ node->SetSymbol(i); node->SetFrequency(CodeLen); }//end if }//end for fTable.close(); }//end for if (fVerbose) cout<<"Trees generated \n"; //At this point the trees are been built } ////////////////////////////////////////////////////////////////////////////////////////////////// void AliTPCCompression::DeleteHuffmanTree(AliTPCHNode* node){ //This function deletes all the nodes of an Huffman tree //In an Huffman tree any internal node has always two children if (node){ DeleteHuffmanTree(node->GetLeft()); DeleteHuffmanTree(node->GetRight()); // cout<GetSymbol()<<" "<<(Int_t)node->GetFrequency()<GetSymbol()<<" "<GetFrequency()<GetLeft()); VisitHuffmanTree(node->GetRight()); } } ////////////////////////////////////////////////////////////////////////////////////////////////// ULong_t AliTPCCompression::ReadWord(Int_t NumberOfBit){ ULong_t Result=0; ULong_t bit=0; for (Int_t i=0;i>fReadBits; fReadBits++; bit=bit<GetRight(); else node=node->GetLeft(); if (!(node->GetLeft())){ symbol=node->GetSymbol(); decoded=1; } }//end while return symbol; } ////////////////////////////////////////////////////////////////////////////////////////////////// Int_t AliTPCCompression::DecompressData(Int_t NumTables,const char* fname,char* fDest){ cout<<" DECOMPRESSION:"<1) BufferFile.FillBuffer(symbol); NextTable(symbol,NextTableType,BunchLen,Count); if(NextTableType==0){ BufferFile.FillBuffer(Time); BufferFile.FillBuffer(BunchLen+2); BunchLen=0; } }//end for BufferFile.WriteTrailer(NumWords,PadNumber,RowNumber,SecNumber); }//end while cout<<"Number of decoded words:"<1) BufferFile.FillBuffer(symbol); NextTable(symbol,NextTableType,BunchLen,Count); if(NextTableType==0){ BufferFile.FillBuffer(Time); BufferFile.FillBuffer(BunchLen+2); BunchLen=0; } }//end for BufferFile.WriteTrailer(NumWords,PadNumber,RowNumber,SecNumber); }//end while if(fVerbose){ cout<<"Number of decoded words:"<