source: trunk/Mars/mbase/MLut.cc@ 14905

Last change on this file since 14905 was 11409, checked in by tbretz, 13 years ago
Some name change to get rid of some compiler warnings.
File size: 9.6 KB
Line 
1/* ======================================================================== *\
2!
3! *
4! * This file is part of CheObs, the Modular Analysis and Reconstruction
5! * Software. It is distributed to you in the hope that it can be a useful
6! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
7! * It is distributed WITHOUT ANY WARRANTY.
8! *
9! * Permission to use, copy, modify and distribute this software and its
10! * documentation for any purpose is hereby granted without fee,
11! * provided that the above copyright notice appears in all copies and
12! * that both that copyright notice and this permission notice appear
13! * in supporting documentation. It is provided "as is" without express
14! * or implied warranty.
15! *
16!
17!
18! Author(s): Thomas Bretz, 1/2009 <mailto:tbretz@astro.uni-wuerzburg.de>
19!
20! Copyright: CheObs Software Development, 2000-2009
21!
22!
23\* ======================================================================== */
24
25//////////////////////////////////////////////////////////////////////////////
26//
27// MLut
28//
29// This is a simple and easy-to-use implementation of a look-up table with
30// rows of different lengths.
31//
32//////////////////////////////////////////////////////////////////////////////
33#include "MLut.h"
34
35#include <errno.h>
36#include <fstream>
37
38#include <stdlib.h> // atoi (Ubuntu 8.10)
39
40#include <TRegexp.h>
41
42#include "MLog.h"
43#include "MLogManip.h"
44
45#include "MArrayI.h"
46
47ClassImp(MLut);
48
49using namespace std;
50
51// --------------------------------------------------------------------------
52//
53// Get the i-th entry in the routing table. Note, that i is not
54// range checked, but for any valid i a valid MArrayI is returned.
55//
56const MArrayI &MLut::GetRow(UInt_t i) const
57{
58 return *static_cast<MArrayI*>(UncheckedAt(i));
59}
60
61void MLut::Delete(Option_t *option)
62{
63 TObjArray::Delete(option);
64
65 fMaxEntries = 0;
66 fMinEntries = 0;
67
68 fMaxIndex = -1;
69}
70
71// --------------------------------------------------------------------------
72//
73// Check if it is a default lut which would just map every entry to itself
74// An empty Lut is a default column
75//
76Bool_t MLut::IsDefaultCol() const
77{
78 if (IsEmpty())
79 return kTRUE;
80
81 if (!HasConstantLength() || fMaxEntries!=1)
82 return kFALSE;
83
84 // Loop over all rows
85 for (Int_t y=0; y<GetEntriesFast(); y++)
86 if (GetRow(y)[0]!=y)
87 return kFALSE;
88
89 return kTRUE;
90}
91
92// --------------------------------------------------------------------------
93//
94// Setup a default lut which just maps n-entris to themself
95//
96void MLut::SetDefaultCol(UInt_t n)
97{
98 Delete();
99
100 for (UInt_t y=0; y<n; y++)
101 {
102
103 MArrayI &idx = *new MArrayI(1);
104 idx[0] = y;
105 Add(&idx);
106 }
107
108 fMinEntries = 1;
109 fMaxEntries = 1;
110
111 fMaxIndex = n;
112}
113
114// --------------------------------------------------------------------------
115//
116// Check if it is a default lut which would just map all entries to one.
117// An empty Lut is a default row
118//
119Bool_t MLut::IsDefaultRow() const
120{
121 if (IsEmpty())
122 return kTRUE;
123
124 if (GetEntriesFast()!=1)
125 return kFALSE;
126
127 const MArrayI &idx = GetRow(0);
128
129 // Loop over all rows
130 for (UInt_t x=0; x<idx.GetSize(); x++)
131 if (UInt_t(idx[x])!=x)
132 return kFALSE;
133
134 return kTRUE;
135}
136
137
138// --------------------------------------------------------------------------
139//
140// Setup a default lut which maps all n-entris to one
141//
142void MLut::SetDefaultRow(UInt_t n)
143{
144 Delete();
145
146 MArrayI &idx = *new MArrayI(n);
147
148 for (UInt_t y=0; y<n; y++)
149 idx[y] = y;
150
151 Add(&idx);
152
153 fMinEntries = n;
154 fMaxEntries = n;
155
156 fMaxIndex = n;
157}
158
159// --------------------------------------------------------------------------
160//
161// Return the inverse lut of the current lut. The user is responsible
162// of deleting the allocated and returned MLut.
163//
164// For an example see Inverse()
165//
166MLut *MLut::GetInverse(Bool_t uniq) const
167{
168 MLut *lut = new MLut;
169 lut->SetInverse(*this, uniq);
170 return lut;
171}
172
173// --------------------------------------------------------------------------
174//
175// Set this to the inverse lut of the given argument.
176//
177// For an example see Inverse()
178//
179void MLut::SetInverse(const MLut &lut, Bool_t uniq)
180{
181 if (&lut==this)
182 {
183 Invert(uniq);
184 return;
185 }
186
187 // Delete the current lut
188 Delete();
189
190 // Add as many MArrayI as needed
191 for (Int_t i=0; i<=lut.fMaxIndex; i++)
192 Add(new MArrayI);
193
194 // Get the number of rows in the given lut
195 const UInt_t num = lut.GetEntriesFast();
196
197 // Loop over all rows
198 for (UInt_t y=0; y<num; y++)
199 {
200 // Get the y-th row
201 const MArrayI &arr = lut.GetRow(y);
202
203 // Loop over all entries in this row
204 for (UInt_t x=0; x<arr.GetSize(); x++)
205 {
206 // If the entry is valid convert it to the right position in
207 // the new lut
208 if (arr[x]<0)
209 continue;
210
211 MArrayI &row = *static_cast<MArrayI*>(UncheckedAt(arr[x]));
212 if (uniq)
213 row.AddUniq(y);
214 else
215 row.Add(y);
216 }
217 }
218
219 // Reset the statistics
220 fMaxEntries = 0;
221 fMinEntries = 0;
222
223 // Loop over all new MArrayI
224 for (Int_t i=0; i<=lut.fMaxIndex; i++)
225 {
226 // Get i-th row
227 MArrayI &row = *static_cast<MArrayI*>(UncheckedAt(i));
228
229 // Sort the i-th row ascending
230 row.ReSort();
231
232 // Get the number of entries in the row
233 UInt_t n = row.GetSize();
234
235 // For convinience (to avoid empty lines in a file)
236 // add -1 to empty rows
237 if (n==0)
238 {
239 row.Add(-1);
240 n=1;
241 }
242
243 // Get the new min and max
244 if (n<fMinEntries || fMinEntries==0)
245 fMinEntries = n;
246 if (n>fMaxEntries)
247 fMaxEntries = n;
248 }
249
250 // set the new highest index in the table
251 fMaxIndex = num-1;
252}
253
254// --------------------------------------------------------------------------
255//
256// Inverts the current lut, for example
257//
258// 0: --
259// 0: 1 2 ---\ 1: 0
260// 1: 2 3 ---/ 2: 0 1
261// 3: 1
262//
263void MLut::Invert(Bool_t uniq)
264{
265 MLut *lut = GetInverse(uniq);
266
267 // Keep fMaxIndex
268 TObjArray::Delete();
269
270 for (Int_t i=0; i<=fMaxIndex; i++)
271 Add(lut->Remove(lut->UncheckedAt(i)));
272
273 fMaxEntries = lut->fMaxEntries;
274 fMinEntries = lut->fMinEntries;
275 fMaxIndex = lut->fMaxIndex;
276
277 delete lut;
278}
279
280// --------------------------------------------------------------------------
281//
282// Read a lut from a stream.
283//
284// The row in the lut is just identical to the line in the stream.
285// The entries in one line must be seperated by a whitespace.
286// The lines can have a different number of entries.
287//
288// Lines which first(!) character is a # are ignored (as they are not
289// existing in the file)
290//
291Int_t MLut::ReadStream(istream &fin)
292{
293 static const TRegexp reg("[^ 1234567890]");
294
295 Delete();
296
297 Int_t l = 0;
298
299 while (1)
300 {
301 TString line;
302 line.ReadLine(fin);
303 if (!fin)
304 break;
305
306 l++;
307
308 if (line[0]=='#')
309 continue;
310
311 if (line.Contains(reg))
312 {
313 gLog << warn << "WARNING - MLut::ReadStream: Line #" << l << " contains invalid character... ignored." << endl;
314 continue;
315 }
316
317 // Split line by whitespaces
318 TObjArray *tokens = line.Tokenize(' ');
319
320 // Get number of entries in this row
321 const UInt_t n = tokens->GetEntries();
322
323 // Calculate minimum and maximum numbers of entries per row
324 if (n<fMinEntries || fMinEntries==0)
325 fMinEntries = n;
326 if (n>fMaxEntries)
327 fMaxEntries = n;
328
329 // create new entry for this row and add it to the array
330 MArrayI &idx = *new MArrayI(n);
331 Add(&idx);
332
333 // loop over all entries in this row
334 for (UInt_t i=0; i<n; i++)
335 {
336 // Convert strings to numbers
337 idx[i] = atoi((*tokens)[i]->GetName());
338
339 // Calculate maximum existing index
340 if (idx[i]>fMaxIndex)
341 fMaxIndex = idx[i];
342 }
343
344 // delete allocated TObjArray
345 delete tokens;
346 }
347
348 return GetEntries();
349}
350
351// --------------------------------------------------------------------------
352//
353// Write a lut to a stream.
354//
355Int_t MLut::WriteStream(ostream &out) const
356{
357 const Int_t n = GetEntriesFast();
358 for (int y=0; y<n; y++)
359 {
360 const MArrayI &arr = GetRow(y);
361
362 if (arr.GetSize()==0)
363 out << -1 << endl;
364
365 for (UInt_t x=0; x<arr.GetSize(); x++)
366 out << arr[x] << " ";
367 out << endl;
368 }
369
370 return n;
371}
372
373// --------------------------------------------------------------------------
374//
375// Read a lut from a file (see also ReadStream)
376//
377Int_t MLut::ReadFile(const char *fname)
378{
379 TString expname(fname);
380 gSystem->ExpandPathName(expname);
381
382 ifstream fin(expname);
383 if (!fin)
384 {
385 gLog << err << "Cannot open file " << expname << ": ";
386 gLog << (errno!=0?strerror(errno):"Insufficient memory for decompression") << endl;
387 return -1;
388 }
389 return ReadStream(fin);
390}
391
392// --------------------------------------------------------------------------
393//
394// Write a lut to a file
395//
396Int_t MLut::WriteFile(const char *fname) const
397{
398 TString expname(fname);
399 gSystem->ExpandPathName(expname);
400
401 ofstream fout(expname);
402 if (!fout)
403 {
404 gLog << err << "Cannot open file " << expname << ": ";
405 gLog << (errno!=0?strerror(errno):"Insufficient memory for decompression") << endl;
406 return -1;
407 }
408
409 return WriteStream(fout);
410}
411
412void MLut::Print(const Option_t *o) const
413{
414 gLog << all;
415 WriteStream(gLog);
416}
Note: See TracBrowser for help on using the repository browser.