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

Last change on this file since 9360 was 9318, checked in by tbretz, 16 years ago
*** empty log message ***
File size: 8.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 lut
73//
74Bool_t MLut::IsDefault() 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::SetDefault(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// Return the inverse lut of the current lut. The user is responsible
115// of deleting the allocated and returned MLut.
116//
117// For an example see Inverse()
118//
119MLut *MLut::GetInverse(Bool_t uniq) const
120{
121 MLut *lut = new MLut;
122 lut->SetInverse(*this, uniq);
123 return lut;
124}
125
126// --------------------------------------------------------------------------
127//
128// Set this to the inverse lut of the given argument.
129//
130// For an example see Inverse()
131//
132void MLut::SetInverse(const MLut &lut, Bool_t uniq)
133{
134 if (&lut==this)
135 {
136 Invert(uniq);
137 return;
138 }
139
140 // Delete the current lut
141 Delete();
142
143 // Add as many MArrayI as needed
144 for (Int_t i=0; i<=lut.fMaxIndex; i++)
145 Add(new MArrayI);
146
147 // Get the number of rows in the given lut
148 const UInt_t num = lut.GetEntriesFast();
149
150 // Loop over all rows
151 for (UInt_t y=0; y<num; y++)
152 {
153 // Get the y-th row
154 const MArrayI &arr = lut.GetRow(y);
155
156 // Loop over all entries in this row
157 for (UInt_t x=0; x<arr.GetSize(); x++)
158 {
159 // If the entry is valid convert it to the right position in
160 // the new lut
161 if (arr[x]<0)
162 continue;
163
164 MArrayI &row = *static_cast<MArrayI*>(UncheckedAt(arr[x]));
165 if (uniq)
166 row.AddUniq(y);
167 else
168 row.Add(y);
169 }
170 }
171
172 // Reset the statistics
173 fMaxEntries = 0;
174 fMinEntries = 0;
175
176 // Loop over all new MArrayI
177 for (Int_t i=0; i<=lut.fMaxIndex; i++)
178 {
179 // Get i-th row
180 MArrayI &row = *static_cast<MArrayI*>(UncheckedAt(i));
181
182 // Sort the i-th row ascending
183 row.ReSort();
184
185 // Get the number of entries in the row
186 UInt_t n = row.GetSize();
187
188 // For convinience (to avoid empty lines in a file)
189 // add -1 to empty rows
190 if (n==0)
191 {
192 row.Add(-1);
193 n=1;
194 }
195
196 // Get the new min and max
197 if (n<fMinEntries || fMinEntries==0)
198 fMinEntries = n;
199 if (n>fMaxEntries)
200 fMaxEntries = n;
201 }
202
203 // set the new highest index in the table
204 fMaxIndex = num-1;
205}
206
207// --------------------------------------------------------------------------
208//
209// Inverts the current lut, for example
210//
211// 0: --
212// 0: 1 2 ---\ 1: 0
213// 1: 2 3 ---/ 2: 0 1
214// 3: 1
215//
216void MLut::Invert(Bool_t uniq)
217{
218 MLut *lut = GetInverse(uniq);
219
220 // Keep fMaxIndex
221 TObjArray::Delete();
222
223 for (Int_t i=0; i<=fMaxIndex; i++)
224 Add(lut->Remove(lut->UncheckedAt(i)));
225
226 fMaxEntries = lut->fMaxEntries;
227 fMinEntries = lut->fMinEntries;
228 fMaxIndex = lut->fMaxIndex;
229
230 delete lut;
231}
232
233// --------------------------------------------------------------------------
234//
235// Read a lut from a stream.
236//
237// The row in the lut is just identical to the line in the stream.
238// The entries in one line must be seperated by a whitespace.
239// The lines can have a different number of entries.
240//
241Int_t MLut::ReadStream(istream &fin)
242{
243 Delete();
244
245 while (1)
246 {
247 TString line;
248 line.ReadLine(fin);
249 if (!fin)
250 break;
251
252 // Split line by whitespaces
253 TObjArray *tokens = line.Tokenize(' ');
254
255 // Get number of entries in this row
256 const UInt_t n = tokens->GetEntries();
257
258 // Calculate minimum and maximum numbers of entries per row
259 if (n<fMinEntries || fMinEntries==0)
260 fMinEntries = n;
261 if (n>fMaxEntries)
262 fMaxEntries = n;
263
264 // create new entry for this row and add it to the array
265 MArrayI &idx = *new MArrayI(n);
266 Add(&idx);
267
268 // loop over all entries in this row
269 for (UInt_t i=0; i<n; i++)
270 {
271 // Convert strings to numbers
272 idx[i] = atoi((*tokens)[i]->GetName());
273
274 // Calculate maximum existing index
275 if (idx[i]>fMaxIndex)
276 fMaxIndex = idx[i];
277 }
278
279 // delete allocated TObjArray
280 delete tokens;
281 }
282
283 return GetEntries();
284}
285
286// --------------------------------------------------------------------------
287//
288// Write a lut to a stream.
289//
290Int_t MLut::WriteStream(ostream &out)
291{
292 const Int_t n = GetEntriesFast();
293 for (int y=0; y<n; y++)
294 {
295 const MArrayI &arr = GetRow(y);
296
297 if (arr.GetSize()==0)
298 out << -1 << endl;
299
300 for (UInt_t x=0; x<arr.GetSize(); x++)
301 out << arr[x] << " ";
302 out << endl;
303 }
304
305 return n;
306}
307
308// --------------------------------------------------------------------------
309//
310// Read a lut from a file (see also ReadStream)
311//
312Int_t MLut::ReadFile(const char *fname)
313{
314 TString expname(fname);
315 gSystem->ExpandPathName(expname);
316
317 ifstream fin(expname);
318 if (!fin)
319 {
320 gLog << err << "Cannot open file " << expname << ": ";
321 gLog << (errno!=0?strerror(errno):"Insufficient memory for decompression") << endl;
322 return -1;
323 }
324 return ReadStream(fin);
325}
326
327// --------------------------------------------------------------------------
328//
329// Write a lut to a file
330//
331Int_t MLut::WriteFile(const char *fname)
332{
333 TString expname(fname);
334 gSystem->ExpandPathName(expname);
335
336 ofstream fout(expname);
337 if (!fout)
338 {
339 gLog << err << "Cannot open file " << expname << ": ";
340 gLog << (errno!=0?strerror(errno):"Insufficient memory for decompression") << endl;
341 return -1;
342 }
343
344 return WriteStream(fout);
345}
Note: See TracBrowser for help on using the repository browser.