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

Last change on this file since 10100 was 9901, checked in by tbretz, 14 years ago
Added the possibility of having comments in MLut.
File size: 9.7 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 n = 0;
298 Int_t l = 0;
299
300 while (1)
301 {
302 TString line;
303 line.ReadLine(fin);
304 if (!fin)
305 break;
306
307 l++;
308
309 if (line[0]=='#')
310 continue;
311
312 n++;
313
314 if (line.Contains(reg))
315 {
316 gLog << warn << "WARNING - MLut::ReadStream: Line #" << l << " contains invalid character... ignored." << endl;
317 continue;
318 }
319
320 // Split line by whitespaces
321 TObjArray *tokens = line.Tokenize(' ');
322
323 // Get number of entries in this row
324 const UInt_t n = tokens->GetEntries();
325
326 // Calculate minimum and maximum numbers of entries per row
327 if (n<fMinEntries || fMinEntries==0)
328 fMinEntries = n;
329 if (n>fMaxEntries)
330 fMaxEntries = n;
331
332 // create new entry for this row and add it to the array
333 MArrayI &idx = *new MArrayI(n);
334 Add(&idx);
335
336 // loop over all entries in this row
337 for (UInt_t i=0; i<n; i++)
338 {
339 // Convert strings to numbers
340 idx[i] = atoi((*tokens)[i]->GetName());
341
342 // Calculate maximum existing index
343 if (idx[i]>fMaxIndex)
344 fMaxIndex = idx[i];
345 }
346
347 // delete allocated TObjArray
348 delete tokens;
349 }
350
351 return GetEntries();
352}
353
354// --------------------------------------------------------------------------
355//
356// Write a lut to a stream.
357//
358Int_t MLut::WriteStream(ostream &out) const
359{
360 const Int_t n = GetEntriesFast();
361 for (int y=0; y<n; y++)
362 {
363 const MArrayI &arr = GetRow(y);
364
365 if (arr.GetSize()==0)
366 out << -1 << endl;
367
368 for (UInt_t x=0; x<arr.GetSize(); x++)
369 out << arr[x] << " ";
370 out << endl;
371 }
372
373 return n;
374}
375
376// --------------------------------------------------------------------------
377//
378// Read a lut from a file (see also ReadStream)
379//
380Int_t MLut::ReadFile(const char *fname)
381{
382 TString expname(fname);
383 gSystem->ExpandPathName(expname);
384
385 ifstream fin(expname);
386 if (!fin)
387 {
388 gLog << err << "Cannot open file " << expname << ": ";
389 gLog << (errno!=0?strerror(errno):"Insufficient memory for decompression") << endl;
390 return -1;
391 }
392 return ReadStream(fin);
393}
394
395// --------------------------------------------------------------------------
396//
397// Write a lut to a file
398//
399Int_t MLut::WriteFile(const char *fname) const
400{
401 TString expname(fname);
402 gSystem->ExpandPathName(expname);
403
404 ofstream fout(expname);
405 if (!fout)
406 {
407 gLog << err << "Cannot open file " << expname << ": ";
408 gLog << (errno!=0?strerror(errno):"Insufficient memory for decompression") << endl;
409 return -1;
410 }
411
412 return WriteStream(fout);
413}
414
415void MLut::Print(const Option_t *o) const
416{
417 gLog << all;
418 WriteStream(gLog);
419}
Note: See TracBrowser for help on using the repository browser.