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

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