Line data Source code
1 : //**************************************************************************
2 : //* This file is property of and copyright by the ALICE HLT Project *
3 : //* ALICE Experiment at CERN, All rights reserved. *
4 : //* *
5 : //* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no> *
6 : //* for The ALICE HLT Project. *
7 : //* *
8 : //* Permission to use, copy, modify and distribute this software and its *
9 : //* documentation strictly for non-commercial purposes is hereby granted *
10 : //* without fee, provided that the above copyright notice appears in all *
11 : //* copies and that both the copyright notice and this permission notice *
12 : //* appear in the supporting documentation. The authors make no claims *
13 : //* about the suitability of this software for any purpose. It is *
14 : //* provided "as is" without express or implied warranty. *
15 : //**************************************************************************
16 :
17 : /// @file AliHLTDataDeflater.cxx
18 : /// @author Matthias Richter, Timm Steinbeck
19 : /// @date 2011-08-10
20 : /// @brief Data deflater class storing only necessary bits
21 : /// @note Code original from AliHLTTPCCompModelDeflater
22 :
23 : #include "AliHLTDataDeflater.h"
24 : #include "AliHLTErrorGuard.h"
25 : #include "TObjArray.h"
26 : #include "TH1I.h"
27 : #include "TH2D.h"
28 : #include "TFile.h"
29 : #include "TMath.h"
30 : #include <memory>
31 : #include <algorithm>
32 : #include <iostream>
33 :
34 : /** ROOT macro for the implementation of ROOT specific class methods */
35 126 : ClassImp(AliHLTDataDeflater)
36 :
37 : AliHLTDataDeflater::AliHLTDataDeflater()
38 0 : : AliHLTLogging()
39 0 : , fBitDataCurrentWord(0)
40 0 : , fBitDataCurrentPosInWord(0)
41 0 : , fBitDataCurrentOutput(NULL)
42 0 : , fBitDataCurrentOutputStart(NULL)
43 0 : , fBitDataCurrentOutputEnd(NULL)
44 0 : , fHistograms(NULL)
45 0 : , fParameterCompression(NULL)
46 0 : , fParameterSize(NULL)
47 0 : {
48 : // constructor, see header file for class documentation
49 0 : if (fHistograms) fHistograms->SetOwner(kTRUE);
50 0 : }
51 :
52 : AliHLTDataDeflater::~AliHLTDataDeflater()
53 0 : {
54 : // destructor
55 0 : Clear();
56 :
57 0 : if (fHistograms)
58 0 : delete fHistograms;
59 0 : fHistograms=NULL;
60 0 : if (fParameterCompression)
61 0 : delete fParameterCompression;
62 0 : fParameterCompression=NULL;
63 0 : if (fParameterSize)
64 0 : delete fParameterSize;
65 0 : fParameterSize=NULL;
66 0 : }
67 :
68 : int AliHLTDataDeflater::InitBitDataOutput( AliHLTUInt8_t* output, UInt_t outputSize)
69 : {
70 : // init the target buffer
71 0 : fBitDataCurrentWord = 0;
72 0 : fBitDataCurrentPosInWord = 7;
73 0 : fBitDataCurrentOutput = fBitDataCurrentOutputStart = output;
74 0 : fBitDataCurrentOutputEnd = output+outputSize;
75 :
76 0 : return 0;
77 : }
78 :
79 : void AliHLTDataDeflater::CloseBitDataOutput()
80 : {
81 : // pad to full byte and clear internal pointer references
82 0 : Pad8Bits();
83 0 : fBitDataCurrentWord=0;
84 0 : fBitDataCurrentPosInWord=0;
85 0 : fBitDataCurrentOutput=NULL;
86 0 : fBitDataCurrentOutputStart=NULL;
87 0 : fBitDataCurrentOutputEnd=NULL;
88 0 : }
89 :
90 : AliHLTUInt8_t AliHLTDataDeflater::GetCurrentOutputByte( Int_t offset ) const
91 : {
92 : // get the current byte
93 0 : if ( !offset )
94 0 : return fBitDataCurrentWord;
95 : else
96 0 : return *(fBitDataCurrentOutput+offset);
97 0 : }
98 :
99 : bool AliHLTDataDeflater::OutputBit( AliHLTUInt32_t const & value )
100 : {
101 : // write one bit to the current byte and position
102 0 : if ( fBitDataCurrentOutput>=fBitDataCurrentOutputEnd )
103 0 : return false;
104 : HLTDebug(" code 0x%08x length 1", value);
105 0 : fBitDataCurrentWord |= (value & 1) << fBitDataCurrentPosInWord;
106 0 : if ( fBitDataCurrentPosInWord )
107 0 : fBitDataCurrentPosInWord--;
108 : else {
109 0 : *fBitDataCurrentOutput = fBitDataCurrentWord;
110 0 : fBitDataCurrentPosInWord = 7;
111 0 : fBitDataCurrentOutput++;
112 0 : fBitDataCurrentWord = 0;
113 : }
114 0 : return true;
115 0 : }
116 :
117 : bool AliHLTDataDeflater::OutputBits( AliHLTUInt64_t const & value, UInt_t const & bitCount )
118 : {
119 : // write bit pattern to the current byte and position
120 0 : if ( bitCount>64 ) {
121 0 : HLTFatal( "Internal error: Attempt to write more than 64 bits (%u)", (unsigned)bitCount );
122 0 : return false;
123 : }
124 : HLTDebug(" code 0x%08x length %d", value, bitCount);
125 : UInt_t bitsToWrite=bitCount;
126 : UInt_t curBitCount;
127 0 : while ( bitsToWrite>0 ) {
128 0 : if ( fBitDataCurrentOutput>=fBitDataCurrentOutputEnd )
129 0 : return false;
130 : #if 1
131 0 : if ( bitsToWrite >= fBitDataCurrentPosInWord+1 )
132 0 : curBitCount = fBitDataCurrentPosInWord+1;
133 : else
134 : curBitCount = bitsToWrite;
135 0 : fBitDataCurrentWord |= ( (value >> (bitsToWrite-curBitCount)) & ((1<<curBitCount)-1) ) << (fBitDataCurrentPosInWord+1-curBitCount);
136 0 : if ( fBitDataCurrentPosInWord < curBitCount )
137 : {
138 0 : *fBitDataCurrentOutput = fBitDataCurrentWord;
139 0 : fBitDataCurrentPosInWord = 7;
140 0 : fBitDataCurrentOutput++;
141 0 : fBitDataCurrentWord = 0;
142 0 : }
143 : else
144 0 : fBitDataCurrentPosInWord -= curBitCount;
145 : bitsToWrite -= curBitCount;
146 :
147 : #else
148 : AliHLTUInt8_t curValue;
149 : if ( bitsToWrite>=8 )
150 : {
151 : curBitCount=8;
152 : curValue = (value >> bitsToWrite-8) & 0xFF;
153 : bitsToWrite -= 8;
154 : }
155 : else
156 : {
157 : curBitCount=bitsToWrite;
158 : curValue = value & ( (1<<bitsToWrite)-1 );
159 : bitsToWrite = 0;
160 : }
161 : if ( fBitDataCurrentPosInWord+1>curBitCount )
162 : {
163 : fBitDataCurrentWord |= curValue << (fBitDataCurrentPosInWord-curBitCount+1);
164 : fBitDataCurrentPosInWord -= curBitCount;
165 : }
166 : else if ( fBitDataCurrentPosInWord+1==curBitCount )
167 : {
168 : fBitDataCurrentWord |= curValue;
169 : *fBitDataCurrentOutput = fBitDataCurrentWord;
170 : fBitDataCurrentPosInWord = 7;
171 : fBitDataCurrentOutput++;
172 : fBitDataCurrentWord = 0;
173 : }
174 : else
175 : {
176 : const UInt_t first = fBitDataCurrentPosInWord+1; // Number of bits for first block
177 : const UInt_t second = curBitCount-first; // Number of bits for second block
178 : fBitDataCurrentWord |= ( curValue >> second ) & ((1<<first)-1);
179 : *fBitDataCurrentOutput = fBitDataCurrentWord;
180 : fBitDataCurrentOutput++;
181 : if ( fBitDataCurrentOutput>=fBitDataCurrentOutputEnd )
182 : return false;
183 : fBitDataCurrentWord = curValue & ((1<<second)-1) << (8-second);
184 : fBitDataCurrentPosInWord = 7-second;
185 : }
186 : #endif
187 : }
188 0 : return true;
189 0 : }
190 :
191 : bool AliHLTDataDeflater::OutputBits( std::bitset<64> const & value, UInt_t const & bitCount )
192 : {
193 : // write bit pattern to the current byte and position
194 0 : if ( bitCount>64 ) {
195 0 : HLTFatal( "Internal error: Attempt to write more than 64 bits (%u)", (unsigned)bitCount );
196 0 : return false;
197 : }
198 : HLTDebug(" code 0x%08x length %d", value.to_ulong(), bitCount);
199 : static const std::bitset<64> mask8bit(255ul);
200 : UInt_t bitsToWrite=bitCount;
201 : UInt_t curBitCount;
202 0 : while ( bitsToWrite>0 ) {
203 0 : if ( fBitDataCurrentOutput>=fBitDataCurrentOutputEnd )
204 0 : return false;
205 0 : if ( bitsToWrite >= fBitDataCurrentPosInWord+1 )
206 0 : curBitCount = fBitDataCurrentPosInWord+1;
207 : else
208 : curBitCount = bitsToWrite;
209 0 : std::bitset<64> valwrite=(value >> (bitsToWrite-curBitCount)) & mask8bit;
210 0 : fBitDataCurrentWord |= ( valwrite.to_ulong() & ((1<<curBitCount)-1) ) << (fBitDataCurrentPosInWord+1-curBitCount);
211 0 : if ( fBitDataCurrentPosInWord < curBitCount )
212 : {
213 0 : *fBitDataCurrentOutput = fBitDataCurrentWord;
214 0 : fBitDataCurrentPosInWord = 7;
215 0 : fBitDataCurrentOutput++;
216 0 : fBitDataCurrentWord = 0;
217 0 : }
218 : else
219 0 : fBitDataCurrentPosInWord -= curBitCount;
220 : bitsToWrite -= curBitCount;
221 0 : }
222 0 : return true;
223 0 : }
224 :
225 : void AliHLTDataDeflater::Pad8Bits()
226 : {
227 : // finish the current word
228 0 : if ( fBitDataCurrentPosInWord==7 )
229 : return;
230 0 : *fBitDataCurrentOutput = fBitDataCurrentWord;
231 0 : fBitDataCurrentPosInWord = 7;
232 0 : fBitDataCurrentOutput++;
233 0 : fBitDataCurrentWord = 0;
234 0 : }
235 :
236 : bool AliHLTDataDeflater::OutputBytes( AliHLTUInt8_t const * data, UInt_t const & byteCount )
237 : {
238 : // write sequence of bytes
239 0 : Pad8Bits();
240 0 : if ( fBitDataCurrentOutput+byteCount>fBitDataCurrentOutputEnd )
241 0 : return false;
242 : HLTDebug(" count %d", byteCount);
243 0 : memcpy( fBitDataCurrentOutput, data, byteCount );
244 0 : fBitDataCurrentOutput += byteCount;
245 0 : return true;
246 0 : }
247 :
248 : bool AliHLTDataDeflater::OutputParameterBits( int parameterId, AliHLTUInt64_t const & value )
249 : {
250 : // write bit pattern of a member to the current byte and position
251 0 : return OutputParameterBits(parameterId, value, 0);
252 : }
253 :
254 : bool AliHLTDataDeflater::OutputParameterBits( int /*(parameterId*/, AliHLTUInt64_t const & /*value*/ , int /*lengthOffset*/)
255 : {
256 : // write bit pattern of a member to the current byte and position
257 0 : ALIHLTERRORGUARD(1,"method needs to be implemented in child class");
258 0 : return false;
259 0 : }
260 :
261 : void AliHLTDataDeflater::Clear(Option_t * /*option*/)
262 : {
263 : // internal cleanup
264 0 : }
265 :
266 : void AliHLTDataDeflater::Print(Option_t *option) const
267 : {
268 : // print info
269 0 : Print(cout, option);
270 0 : }
271 :
272 : void AliHLTDataDeflater::Print(ostream& out, Option_t */*option*/) const
273 : {
274 : // print to stream
275 0 : out << "AliHLTDataDeflater: " << endl;
276 0 : out << " start " << (void*)fBitDataCurrentOutputStart;
277 0 : out << " end " << (void*)fBitDataCurrentOutputEnd << endl;
278 0 : out << " current " << (void*)fBitDataCurrentOutput;
279 0 : out << " position in word: " << fBitDataCurrentPosInWord << endl;
280 0 : }
281 :
282 : ostream& operator<<(ostream &out, const AliHLTDataDeflater& me)
283 : {
284 0 : me.Print(out);
285 0 : return out;
286 : }
287 :
288 : int AliHLTDataDeflater::EnableStatistics()
289 : {
290 : /// enable statistics accounting
291 0 : if (!fHistograms) {
292 0 : fHistograms=new TObjArray;
293 0 : if (!fHistograms) return -ENOMEM;
294 0 : fHistograms->SetOwner(kTRUE);
295 0 : }
296 0 : return 0;
297 0 : }
298 :
299 : int AliHLTDataDeflater::AddHistogram(int id, const char* name, int bitWidth, TH1* h)
300 : {
301 : /// add a histogram for deflater statistic of the corresponding parameter
302 : /// a histogram is created with default settings if h is not specified; if
303 : /// provided, the ownership goes over to the base class
304 0 : if (!fHistograms) {
305 0 : fHistograms=new TObjArray;
306 0 : if (!fHistograms) return -ENOMEM;
307 0 : fHistograms->SetOwner(kTRUE);
308 0 : }
309 0 : if (id>=0 && fHistograms->GetEntriesFast()>id && fHistograms->At(id)!=NULL) {
310 0 : HLTWarning("parameter with id %d has existing object (%s), skipping histogram %s",
311 : id, fHistograms->At(id)->GetName(), h?h->GetName():name);
312 0 : return -EEXIST;
313 : }
314 0 : if (id<0 && h!=NULL && fHistograms->FindObject(h->GetName())) {
315 0 : HLTWarning("parameter with name %s already existing, skipping histogram", h->GetName());
316 0 : return -EEXIST;
317 : }
318 0 : if (!h)
319 0 : h=new TH1I(name, name, 100, 0, 1<<bitWidth);
320 0 : if (!h) return -ENOMEM;
321 0 : fHistograms->Add(h);
322 0 : return 0;
323 0 : }
324 :
325 : int AliHLTDataDeflater::FillStatistics(int id, AliHLTUInt64_t value, unsigned length, float codingWeight)
326 : {
327 : /// fill statistics for a parameter
328 0 : if (!fHistograms ||
329 0 : fHistograms->GetEntriesFast()<=id ||
330 0 : id<0) return 0;
331 :
332 0 : if (value<(~(AliHLTUInt64_t)0)) {
333 0 : TObject* o=fHistograms->At(id);
334 0 : if (o) {
335 0 : TH1* h=dynamic_cast<TH1*>(o);
336 0 : if (h) {
337 0 : h->Fill(value);
338 0 : }
339 0 : }
340 0 : }
341 :
342 0 : if (!fParameterCompression) {
343 0 : int bins=fHistograms->GetEntriesFast();
344 0 : fParameterCompression=new TH2D("ParameterCompression", "ParameterCompression", bins, 0, bins, 1000, 0., 5.0);
345 0 : }
346 0 : if (fParameterCompression && codingWeight>=.0) {
347 0 : fParameterCompression->Fill(id, codingWeight);
348 0 : }
349 0 : if (!fParameterSize) {
350 0 : int bins=fHistograms->GetEntriesFast();
351 0 : fParameterSize=new TH2D("ParameterSize", "ParameterSize", bins, 0, bins, 1000, 0., 64.0);
352 0 : }
353 0 : if (fParameterSize && length>0) {
354 0 : fParameterSize->Fill(id, length);
355 0 : }
356 :
357 0 : return 0;
358 0 : }
359 :
360 : void AliHLTDataDeflater::SaveAs(const char *filename,Option_t */*option*/) const
361 : {
362 : // safe histograms to file
363 0 : std::auto_ptr<TFile> file(TFile::Open(filename, "RECREATE"));
364 0 : if (!file.get() || file->IsZombie()) {
365 0 : HLTError("can not open file %s", filename);;
366 0 : return;
367 : }
368 0 : file->cd();
369 0 : if (fHistograms) {
370 0 : for (int i=0; i<fHistograms->GetEntries(); i++) {
371 0 : if (fHistograms->At(i)==NULL ||
372 0 : !fHistograms->At(i)->InheritsFrom("TH1") ||
373 0 : fHistograms->At(i)->InheritsFrom("TH2") ||
374 0 : fHistograms->At(i)->InheritsFrom("TH3")
375 : ) continue; // only TH1 objects in the list
376 0 : TH1* h=reinterpret_cast<TH1*>(fHistograms->At(i));
377 0 : if (!h) continue;
378 0 : float entropy=CalcEntropy(h);
379 0 : if (entropy<0) continue;
380 0 : TString title=h->GetTitle();
381 0 : title+=Form(" entropy %.2f", entropy);
382 0 : h->SetTitle(title);
383 0 : }
384 0 : fHistograms->Write();
385 0 : if (fParameterCompression)
386 0 : fParameterCompression->Write();
387 0 : if (fParameterSize)
388 0 : fParameterSize->Write();
389 : }
390 :
391 0 : file->Close();
392 0 : }
393 :
394 : float AliHLTDataDeflater::CalcEntropy(TH1* histo, const char* /*option*/, int mode)
395 : {
396 :
397 0 : if (!histo) return -1000.;
398 :
399 0 : float l2=TMath::Log(2.0);
400 0 : float integral=histo->Integral(0,histo->GetNbinsX());
401 0 : int centerbin=mode*histo->GetNbinsX()/2;
402 0 : int nofBins=histo->GetNbinsX()-centerbin;
403 : float entropy=0.0;
404 0 : for (int offset=0; offset<nofBins; offset++) {
405 0 : float abundance=histo->GetBinContent(offset);
406 0 : if (abundance<1.0) continue;
407 0 : entropy += (- (Double_t) abundance / (Double_t) integral ) * log( ( (Double_t) abundance / (Double_t) integral )) / (l2);
408 0 : }
409 :
410 : return entropy;
411 0 : }
|