3 //**************************************************************************
4 //* This file is property of and copyright by the ALICE HLT Project *
5 //* ALICE Experiment at CERN, All rights reserved. *
7 //* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no> *
8 //* for The ALICE HLT Project. *
10 //* Permission to use, copy, modify and distribute this software and its *
11 //* documentation strictly for non-commercial purposes is hereby granted *
12 //* without fee, provided that the above copyright notice appears in all *
13 //* copies and that both the copyright notice and this permission notice *
14 //* appear in the supporting documentation. The authors make no claims *
15 //* about the suitability of this software for any purpose. It is *
16 //* provided "as is" without express or implied warranty. *
17 //**************************************************************************
19 /// @file AliHLTDataDeflater.cxx
20 /// @author Matthias Richter, Timm Steinbeck
22 /// @brief Data deflater class storing only necessary bits
23 /// @note Code original from AliHLTTPCCompModelDeflater
25 #include "AliHLTDataDeflater.h"
26 #include "AliHLTErrorGuard.h"
27 #include "TObjArray.h"
36 /** ROOT macro for the implementation of ROOT specific class methods */
37 ClassImp(AliHLTDataDeflater)
39 AliHLTDataDeflater::AliHLTDataDeflater()
41 , fBitDataCurrentWord(0)
42 , fBitDataCurrentPosInWord(0)
43 , fBitDataCurrentOutput(NULL)
44 , fBitDataCurrentOutputStart(NULL)
45 , fBitDataCurrentOutputEnd(NULL)
47 , fParameterCompression(NULL)
48 , fParameterSize(NULL)
50 // see header file for class documentation
52 // refer to README to build package
54 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
55 if (fHistograms) fHistograms->SetOwner(kTRUE);
58 AliHLTDataDeflater::~AliHLTDataDeflater()
66 if (fParameterCompression)
67 delete fParameterCompression;
68 fParameterCompression=NULL;
70 delete fParameterSize;
74 int AliHLTDataDeflater::InitBitDataOutput( AliHLTUInt8_t* output, UInt_t outputSize)
76 // init the target buffer
77 fBitDataCurrentWord = 0;
78 fBitDataCurrentPosInWord = 7;
79 fBitDataCurrentOutput = fBitDataCurrentOutputStart = output;
80 fBitDataCurrentOutputEnd = output+outputSize;
85 void AliHLTDataDeflater::CloseBitDataOutput()
87 // pad to full byte and clear internal pointer references
89 fBitDataCurrentWord=0;
90 fBitDataCurrentPosInWord=0;
91 fBitDataCurrentOutput=NULL;
92 fBitDataCurrentOutputStart=NULL;
93 fBitDataCurrentOutputEnd=NULL;
96 AliHLTUInt8_t AliHLTDataDeflater::GetCurrentOutputByte( Int_t offset ) const
98 // get the current byte
100 return fBitDataCurrentWord;
102 return *(fBitDataCurrentOutput+offset);
105 bool AliHLTDataDeflater::OutputBit( AliHLTUInt32_t const & value )
107 // write one bit to the current byte and position
108 if ( fBitDataCurrentOutput>=fBitDataCurrentOutputEnd )
110 fBitDataCurrentWord |= (value & 1) << fBitDataCurrentPosInWord;
111 if ( fBitDataCurrentPosInWord )
112 fBitDataCurrentPosInWord--;
114 *fBitDataCurrentOutput = fBitDataCurrentWord;
115 fBitDataCurrentPosInWord = 7;
116 fBitDataCurrentOutput++;
117 fBitDataCurrentWord = 0;
122 bool AliHLTDataDeflater::OutputBits( AliHLTUInt64_t const & value, UInt_t const & bitCount )
124 // write bit pattern to the current byte and position
126 HLTFatal( "Internal error: Attempt to write more than 64 bits (%u)", (unsigned)bitCount );
129 UInt_t bitsToWrite=bitCount;
131 while ( bitsToWrite>0 ) {
132 if ( fBitDataCurrentOutput>=fBitDataCurrentOutputEnd )
135 if ( bitsToWrite >= fBitDataCurrentPosInWord+1 )
136 curBitCount = fBitDataCurrentPosInWord+1;
138 curBitCount = bitsToWrite;
139 fBitDataCurrentWord |= ( (value >> (bitsToWrite-curBitCount)) & ((1<<curBitCount)-1) ) << (fBitDataCurrentPosInWord+1-curBitCount);
140 if ( fBitDataCurrentPosInWord < curBitCount )
142 *fBitDataCurrentOutput = fBitDataCurrentWord;
143 fBitDataCurrentPosInWord = 7;
144 fBitDataCurrentOutput++;
145 fBitDataCurrentWord = 0;
148 fBitDataCurrentPosInWord -= curBitCount;
149 bitsToWrite -= curBitCount;
152 AliHLTUInt8_t curValue;
153 if ( bitsToWrite>=8 )
156 curValue = (value >> bitsToWrite-8) & 0xFF;
161 curBitCount=bitsToWrite;
162 curValue = value & ( (1<<bitsToWrite)-1 );
165 if ( fBitDataCurrentPosInWord+1>curBitCount )
167 fBitDataCurrentWord |= curValue << (fBitDataCurrentPosInWord-curBitCount+1);
168 fBitDataCurrentPosInWord -= curBitCount;
170 else if ( fBitDataCurrentPosInWord+1==curBitCount )
172 fBitDataCurrentWord |= curValue;
173 *fBitDataCurrentOutput = fBitDataCurrentWord;
174 fBitDataCurrentPosInWord = 7;
175 fBitDataCurrentOutput++;
176 fBitDataCurrentWord = 0;
180 const UInt_t first = fBitDataCurrentPosInWord+1; // Number of bits for first block
181 const UInt_t second = curBitCount-first; // Number of bits for second block
182 fBitDataCurrentWord |= ( curValue >> second ) & ((1<<first)-1);
183 *fBitDataCurrentOutput = fBitDataCurrentWord;
184 fBitDataCurrentOutput++;
185 if ( fBitDataCurrentOutput>=fBitDataCurrentOutputEnd )
187 fBitDataCurrentWord = curValue & ((1<<second)-1) << (8-second);
188 fBitDataCurrentPosInWord = 7-second;
195 bool AliHLTDataDeflater::OutputBits( std::bitset<64> const & value, UInt_t const & bitCount )
197 // write bit pattern to the current byte and position
199 HLTFatal( "Internal error: Attempt to write more than 64 bits (%u)", (unsigned)bitCount );
202 static const std::bitset<64> mask8bit(255ul);
203 UInt_t bitsToWrite=bitCount;
205 while ( bitsToWrite>0 ) {
206 if ( fBitDataCurrentOutput>=fBitDataCurrentOutputEnd )
208 if ( bitsToWrite >= fBitDataCurrentPosInWord+1 )
209 curBitCount = fBitDataCurrentPosInWord+1;
211 curBitCount = bitsToWrite;
212 std::bitset<64> valwrite=(value >> (bitsToWrite-curBitCount)) & mask8bit;
213 fBitDataCurrentWord |= ( valwrite.to_ulong() & ((1<<curBitCount)-1) ) << (fBitDataCurrentPosInWord+1-curBitCount);
214 if ( fBitDataCurrentPosInWord < curBitCount )
216 *fBitDataCurrentOutput = fBitDataCurrentWord;
217 fBitDataCurrentPosInWord = 7;
218 fBitDataCurrentOutput++;
219 fBitDataCurrentWord = 0;
222 fBitDataCurrentPosInWord -= curBitCount;
223 bitsToWrite -= curBitCount;
228 void AliHLTDataDeflater::Pad8Bits()
230 // finish the current word
231 if ( fBitDataCurrentPosInWord==7 )
233 *fBitDataCurrentOutput = fBitDataCurrentWord;
234 fBitDataCurrentPosInWord = 7;
235 fBitDataCurrentOutput++;
236 fBitDataCurrentWord = 0;
239 bool AliHLTDataDeflater::OutputBytes( AliHLTUInt8_t const * data, UInt_t const & byteCount )
241 // write sequence of bytes
243 if ( fBitDataCurrentOutput+byteCount>fBitDataCurrentOutputEnd )
245 memcpy( fBitDataCurrentOutput, data, byteCount );
246 fBitDataCurrentOutput += byteCount;
250 bool AliHLTDataDeflater::OutputParameterBits( int parameterId, AliHLTUInt64_t const & value )
252 // write bit pattern of a member to the current byte and position
253 return OutputParameterBits(parameterId, value, 0);
256 bool AliHLTDataDeflater::OutputParameterBits( int /*(parameterId*/, AliHLTUInt64_t const & /*value*/ , int /*lengthOffset*/)
258 // write bit pattern of a member to the current byte and position
259 ALIHLTERRORGUARD(1,"method needs to be implemented in child class");
263 void AliHLTDataDeflater::Clear(Option_t * /*option*/)
268 void AliHLTDataDeflater::Print(Option_t *option) const
274 void AliHLTDataDeflater::Print(ostream& out, Option_t */*option*/) const
277 out << "AliHLTDataDeflater: " << endl;
280 ostream& operator<<(ostream &out, const AliHLTDataDeflater& me)
286 int AliHLTDataDeflater::EnableStatistics()
288 /// enable statistics accounting
290 fHistograms=new TObjArray;
291 if (!fHistograms) return -ENOMEM;
292 fHistograms->SetOwner(kTRUE);
297 int AliHLTDataDeflater::AddHistogram(int id, const char* name, int bitWidth, TH1* h)
299 /// add a histogram for deflater statistic of the corresponding parameter
300 /// a histogram is created with default settings if h is not specified; if
301 /// provided, the ownership goes over to the base class
303 fHistograms=new TObjArray;
304 if (!fHistograms) return -ENOMEM;
305 fHistograms->SetOwner(kTRUE);
307 if (id>=0 && fHistograms->GetEntriesFast()>id && fHistograms->At(id)!=NULL) {
308 HLTWarning("parameter with id %d has existing object (%s), skipping histogram %s",
309 id, fHistograms->At(id)->GetName(), h?h->GetName():name);
312 if (id<0 && h!=NULL && fHistograms->FindObject(h->GetName())) {
313 HLTWarning("parameter with name %s already existing, skipping histogram", h->GetName());
317 h=new TH1I(name, name, 100, 0, 1<<bitWidth);
318 if (!h) return -ENOMEM;
323 int AliHLTDataDeflater::FillStatistics(int id, AliHLTUInt64_t value, unsigned length, float codingWeight)
325 /// fill statistics for a parameter
327 fHistograms->GetEntriesFast()<=id ||
330 TObject* o=fHistograms->At(id);
332 TH1* h=dynamic_cast<TH1*>(o);
338 if (!fParameterCompression) {
339 int bins=fHistograms->GetEntriesFast();
340 fParameterCompression=new TH2D("ParameterCompression", "ParameterCompression", bins, 0, bins, 1000, 0., 5.0);
342 if (fParameterCompression) {
343 fParameterCompression->Fill(id, codingWeight);
345 if (!fParameterSize) {
346 int bins=fHistograms->GetEntriesFast();
347 fParameterSize=new TH2D("ParameterSize", "ParameterSize", bins, 0, bins, 1000, 0., 64.0);
349 if (fParameterSize) {
350 fParameterSize->Fill(id, length);
356 void AliHLTDataDeflater::SaveAs(const char *filename,Option_t */*option*/) const
358 // safe histograms to file
359 std::auto_ptr<TFile> file(TFile::Open(filename, "RECREATE"));
360 if (!file.get() || file->IsZombie()) {
361 HLTError("can not open file %s", filename);;
366 for (int i=0; i<fHistograms->GetEntries(); i++) {
367 if (fHistograms->At(i)==NULL ||
368 !fHistograms->At(i)->InheritsFrom("TH1") ||
369 fHistograms->At(i)->InheritsFrom("TH2") ||
370 fHistograms->At(i)->InheritsFrom("TH3")
371 ) continue; // only TH1 objects in the list
372 TH1* h=reinterpret_cast<TH1*>(fHistograms->At(i));
374 float entropy=CalcEntropy(h);
375 if (entropy<0) continue;
376 TString title=h->GetTitle();
377 title+=Form(" entropy %.2f", entropy);
380 fHistograms->Write();
381 if (fParameterCompression)
382 fParameterCompression->Write();
384 fParameterSize->Write();
390 float AliHLTDataDeflater::CalcEntropy(TH1* histo, const char* /*option*/, int mode)
393 if (!histo) return -1000.;
395 float l2=TMath::Log(2.0);
396 float integral=histo->Integral(0,histo->GetNbinsX());
397 int centerbin=mode*histo->GetNbinsX()/2;
398 int nofBins=histo->GetNbinsX()-centerbin;
400 for (int offset=0; offset<nofBins; offset++) {
401 float abundance=histo->GetBinContent(offset);
402 if (abundance<1.0) continue;
403 entropy += (- (Double_t) abundance / (Double_t) integral ) * log( ( (Double_t) abundance / (Double_t) integral )) / (l2);