source: trunk/MagicSoft/Mars/mbase/MLut.cc@ 9464

Last change on this file since 9464 was 9462, checked in by tbretz, 15 years ago
*** empty log message ***
File size: 9.2 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 "MLog.h"
41#include "MLogManip.h"
42
43#include "MArrayI.h"
44
45ClassImp(MLut);
46
47using namespace std;
48
49// --------------------------------------------------------------------------
50//
51// Get the i-th entry in the routing table. Note, that i is not
52// range checked, but for any valid i a valid MArrayI is returned.
53//
54const MArrayI &MLut::GetRow(UInt_t i) const
55{
56 return *static_cast<MArrayI*>(UncheckedAt(i));
57}
58
59void MLut::Delete(Option_t *option)
60{
61 TObjArray::Delete(option);
62
63 fMaxEntries = 0;
64 fMinEntries = 0;
65
66 fMaxIndex = -1;
67}
68
69// --------------------------------------------------------------------------
70//
71// Check if it is a default lut which would just map every entry to itself
72// An empty Lut is a default column
73//
74Bool_t MLut::IsDefaultCol() const
75{
76 if (IsEmpty())
77 return kTRUE;
78
79 if (!HasConstantLength() || fMaxEntries!=1)
80 return kFALSE;
81
82 // Loop over all rows
83 for (Int_t y=0; y<GetEntriesFast(); y++)
84 if (GetRow(y)[0]!=y)
85 return kFALSE;
86
87 return kTRUE;
88}
89
90// --------------------------------------------------------------------------
91//
92// Setup a default lut which just maps n-entris to themself
93//
94void MLut::SetDefaultCol(UInt_t n)
95{
96 Delete();
97
98 for (UInt_t y=0; y<n; y++)
99 {
100
101 MArrayI &idx = *new MArrayI(1);
102 idx[0] = y;
103 Add(&idx);
104 }
105
106 fMinEntries = 1;
107 fMaxEntries = 1;
108
109 fMaxIndex = n;
110}
111
112// --------------------------------------------------------------------------
113//
114// Check if it is a default lut which would just map all entries to one.
115// An empty Lut is a default row
116//
117Bool_t MLut::IsDefaultRow() const
118{
119 if (IsEmpty())
120 return kTRUE;
121
122 if (GetEntriesFast()!=1)
123 return kFALSE;
124
125 const MArrayI &idx = GetRow(0);
126
127 // Loop over all rows
128 for (UInt_t x=0; x<idx.GetSize(); x++)
129 if (UInt_t(idx[x])!=x)
130 return kFALSE;
131
132 return kTRUE;
133}
134
135
136// --------------------------------------------------------------------------
137//
138// Setup a default lut which maps all n-entris to one
139//
140void MLut::SetDefaultRow(UInt_t n)
141{
142 Delete();
143
144 MArrayI &idx = *new MArrayI(n);
145
146 for (UInt_t y=0; y<n; y++)
147 idx[y] = y;
148
149 Add(&idx);
150
151 fMinEntries = n;
152 fMaxEntries = n;
153
154 fMaxIndex = n;
155}
156
157// --------------------------------------------------------------------------
158//
159// Return the inverse lut of the current lut. The user is responsible
160// of deleting the allocated and returned MLut.
161//
162// For an example see Inverse()
163//
164MLut *MLut::GetInverse(Bool_t uniq) const
165{
166 MLut *lut = new MLut;
167 lut->SetInverse(*this, uniq);
168 return lut;
169}
170
171// --------------------------------------------------------------------------
172//
173// Set this to the inverse lut of the given argument.
174//
175// For an example see Inverse()
176//
177void MLut::SetInverse(const MLut &lut, Bool_t uniq)
178{
179 if (&lut==this)
180 {
181 Invert(uniq);
182 return;
183 }
184
185 // Delete the current lut
186 Delete();
187
188 // Add as many MArrayI as needed
189 for (Int_t i=0; i<=lut.fMaxIndex; i++)
190 Add(new MArrayI);
191
192 // Get the number of rows in the given lut
193 const UInt_t num = lut.GetEntriesFast();
194
195 // Loop over all rows
196 for (UInt_t y=0; y<num; y++)
197 {
198 // Get the y-th row
199 const MArrayI &arr = lut.GetRow(y);
200
201 // Loop over all entries in this row
202 for (UInt_t x=0; x<arr.GetSize(); x++)
203 {
204 // If the entry is valid convert it to the right position in
205 // the new lut
206 if (arr[x]<0)
207 continue;
208
209 MArrayI &row = *static_cast<MArrayI*>(UncheckedAt(arr[x]));
210 if (uniq)
211 row.AddUniq(y);
212 else
213 row.Add(y);
214 }
215 }
216
217 // Reset the statistics
218 fMaxEntries = 0;
219 fMinEntries = 0;
220
221 // Loop over all new MArrayI
222 for (Int_t i=0; i<=lut.fMaxIndex; i++)
223 {
224 // Get i-th row
225 MArrayI &row = *static_cast<MArrayI*>(UncheckedAt(i));
226
227 // Sort the i-th row ascending
228 row.ReSort();
229
230 // Get the number of entries in the row
231 UInt_t n = row.GetSize();
232
233 // For convinience (to avoid empty lines in a file)
234 // add -1 to empty rows
235 if (n==0)
236 {
237 row.Add(-1);
238 n=1;
239 }
240
241 // Get the new min and max
242 if (n<fMinEntries || fMinEntries==0)
243 fMinEntries = n;
244 if (n>fMaxEntries)
245 fMaxEntries = n;
246 }
247
248 // set the new highest index in the table
249 fMaxIndex = num-1;
250}
251
252// --------------------------------------------------------------------------
253//
254// Inverts the current lut, for example
255//
256// 0: --
257// 0: 1 2 ---\ 1: 0
258// 1: 2 3 ---/ 2: 0 1
259// 3: 1
260//
261void MLut::Invert(Bool_t uniq)
262{
263 MLut *lut = GetInverse(uniq);
264
265 // Keep fMaxIndex
266 TObjArray::Delete();
267
268 for (Int_t i=0; i<=fMaxIndex; i++)
269 Add(lut->Remove(lut->UncheckedAt(i)));
270
271 fMaxEntries = lut->fMaxEntries;
272 fMinEntries = lut->fMinEntries;
273 fMaxIndex = lut->fMaxIndex;
274
275 delete lut;
276}
277
278// --------------------------------------------------------------------------
279//
280// Read a lut from a stream.
281//
282// The row in the lut is just identical to the line in the stream.
283// The entries in one line must be seperated by a whitespace.
284// The lines can have a different number of entries.
285//
286Int_t MLut::ReadStream(istream &fin)
287{
288 Delete();
289
290 while (1)
291 {
292 TString line;
293 line.ReadLine(fin);
294 if (!fin)
295 break;
296
297 // Split line by whitespaces
298 TObjArray *tokens = line.Tokenize(' ');
299
300 // Get number of entries in this row
301 const UInt_t n = tokens->GetEntries();
302
303 // Calculate minimum and maximum numbers of entries per row
304 if (n<fMinEntries || fMinEntries==0)
305 fMinEntries = n;
306 if (n>fMaxEntries)
307 fMaxEntries = n;
308
309 // create new entry for this row and add it to the array
310 MArrayI &idx = *new MArrayI(n);
311 Add(&idx);
312
313 // loop over all entries in this row
314 for (UInt_t i=0; i<n; i++)
315 {
316 // Convert strings to numbers
317 idx[i] = atoi((*tokens)[i]->GetName());
318
319 // Calculate maximum existing index
320 if (idx[i]>fMaxIndex)
321 fMaxIndex = idx[i];
322 }
323
324 // delete allocated TObjArray
325 delete tokens;
326 }
327
328 return GetEntries();
329}
330
331// --------------------------------------------------------------------------
332//
333// Write a lut to a stream.
334//
335Int_t MLut::WriteStream(ostream &out) const
336{
337 const Int_t n = GetEntriesFast();
338 for (int y=0; y<n; y++)
339 {
340 const MArrayI &arr = GetRow(y);
341
342 if (arr.GetSize()==0)
343 out << -1 << endl;
344
345 for (UInt_t x=0; x<arr.GetSize(); x++)
346 out << arr[x] << " ";
347 out << endl;
348 }
349
350 return n;
351}
352
353// --------------------------------------------------------------------------
354//
355// Read a lut from a file (see also ReadStream)
356//
357Int_t MLut::ReadFile(const char *fname)
358{
359 TString expname(fname);
360 gSystem->ExpandPathName(expname);
361
362 ifstream fin(expname);
363 if (!fin)
364 {
365 gLog << err << "Cannot open file " << expname << ": ";
366 gLog << (errno!=0?strerror(errno):"Insufficient memory for decompression") << endl;
367 return -1;
368 }
369 return ReadStream(fin);
370}
371
372// --------------------------------------------------------------------------
373//
374// Write a lut to a file
375//
376Int_t MLut::WriteFile(const char *fname) const
377{
378 TString expname(fname);
379 gSystem->ExpandPathName(expname);
380
381 ofstream fout(expname);
382 if (!fout)
383 {
384 gLog << err << "Cannot open file " << expname << ": ";
385 gLog << (errno!=0?strerror(errno):"Insufficient memory for decompression") << endl;
386 return -1;
387 }
388
389 return WriteStream(fout);
390}
391
392void MLut::Print(const Option_t *o) const
393{
394 gLog << all;
395 WriteStream(gLog);
396}
Note: See TracBrowser for help on using the repository browser.