source: branches/AddingGoogleTestEnvironment/msimreflector/MReflector.cc@ 19503

Last change on this file since 19503 was 9947, checked in by tbretz, 14 years ago
Implemented a new mirror type MMirrorHex90 and a possibility to write a file with a relfector definition.
File size: 13.0 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// MReflector
28//
29//////////////////////////////////////////////////////////////////////////////
30#include "MReflector.h"
31
32#include <fstream>
33#include <errno.h>
34
35#include <stdlib.h> // atof (Ubuntu 8.10)
36
37#include <TClass.h>
38#include <TSystem.h>
39#include <TEllipse.h>
40
41#include "MQuaternion.h"
42#include "MMirror.h"
43
44#include "MLog.h"
45#include "MLogManip.h"
46
47#include "MH.h"
48
49ClassImp(MReflector);
50
51using namespace std;
52
53// --------------------------------------------------------------------------
54//
55// Default constructor
56//
57MReflector::MReflector(const char *name, const char *title)
58{
59 fName = name ? name : "MReflector";
60 fTitle = title ? title : "Parameter container storing a collection of several mirrors (reflector)";
61
62 fMirrors.SetOwner();
63}
64
65// --------------------------------------------------------------------------
66//
67// Set the SigmaPSF of all mirrors currently stored.
68//
69void MReflector::SetSigmaPSF(Double_t psf)
70{
71 fMirrors.R__FOR_EACH(MMirror, SetSigmaPSF)(psf);
72}
73
74// --------------------------------------------------------------------------
75//
76// Calculate the maximum radius of th ereflector. This is not meant as
77// a precise number but as a rough estimate e.g. to bin a histogram.
78//
79void MReflector::InitMaxR()
80{
81 fMaxR = 0;
82
83 TIter Next(&fMirrors);
84 MMirror *m = 0;
85 while ((m=static_cast<MMirror*>(Next())))
86 {
87 // Take into account the maximum incident angle 8eg 10deg) and
88 // the theta-angle of the mirror and the z-distance.
89 const Double_t r = m->GetDist()+1.5*m->GetMaxR();
90 if (r > fMaxR)
91 fMaxR = r;
92 }
93}
94
95// --------------------------------------------------------------------------
96//
97// Return the total Area of all mirrors. Note, that it is recalculated
98// with any call.
99//
100Double_t MReflector::GetA() const
101{
102 Double_t A = 0;
103
104 TIter Next(&fMirrors);
105 MMirror *m = 0;
106 while ((m=static_cast<MMirror*>(Next())))
107 A += m->GetA();
108
109 return A;
110}
111
112// --------------------------------------------------------------------------
113//
114// Get the pointer to the first mirror. This is a very dangerous way of
115// access, but the fastest possible. because it is the most often called
116// function in ExecuteReflector we have to have a very fast access.
117//
118const MMirror **MReflector::GetFirstPtr() const
119{
120 return (const MMirror**)fMirrors.GetObjectRef(0);
121}
122
123// --------------------------------------------------------------------------
124//
125// Get number of mirrors. There should be no holes in the array!
126//
127const UInt_t MReflector::GetNumMirrors() const
128{
129 return fMirrors.GetEntriesFast();
130}
131
132// --------------------------------------------------------------------------
133//
134// Check with a rough estimate whether a photon can hit the reflector.
135//
136Bool_t MReflector::CanHit(const MQuaternion &p) const
137{
138 // p is given in the reflectory coordinate frame. This is meant as a
139 // fast check without lengthy calculations to omit all photons which
140 // cannot hit the reflector at all
141 return p.R2()<fMaxR*fMaxR;
142}
143
144// --------------------------------------------------------------------------
145//
146// I/O helper for ReadFile to avoid calling "delete arr" before every return
147//
148MMirror *MReflector::EvalTokens(TObjArray &arr, Double_t defpsf) const
149{
150 if (arr.GetEntries()<9)
151 {
152 *fLog << err << "ERROR - Not enough arguments..." << endl;
153 return 0;
154 }
155
156 const TVector3 pos(atof(arr[0]->GetName()),
157 atof(arr[1]->GetName()),
158 atof(arr[2]->GetName()));
159
160 const TVector3 norm(atof(arr[3]->GetName()),
161 atof(arr[4]->GetName()),
162 atof(arr[5]->GetName()));
163
164 UInt_t n = 6;
165
166 TString six = arr[n]->GetName();
167
168 Char_t shape = 'S';
169 if (!six.IsFloat())
170 {
171 shape = six[0];
172 n++;
173 }
174
175 const Double_t F = atof(arr[n++]->GetName());
176
177 const TString val = arr[n++]->GetName();
178
179 const Double_t psf = val.IsFloat() ? val.Atof() : -1;
180
181 n += val.IsFloat() ? 1 : 0;
182
183 TString type = arr[n-1]->GetName();
184 type.Prepend("MMirror");
185
186 for (UInt_t i=0; i<n; i++)
187 delete arr.RemoveAt(i);
188 arr.Compress();
189
190 TString msg;
191 TClass *cls = MParContainer::GetClass(type);
192 if (!cls)
193 {
194 *fLog << err << "ERROR - Class " << type << " not in dictionary." << endl;
195 return 0;
196 }
197
198 if (!cls->InheritsFrom(MMirror::Class()))
199 {
200 *fLog << err << "ERROR - Cannot create new instance of class " << type << ": " << endl;
201 *fLog << "Class doesn't inherit from MMirror." << endl;
202 return 0;
203 }
204
205 MMirror *m = static_cast<MMirror*>(cls->New());
206 if (!m)
207 {
208 *fLog << err << "ERROR - Cannot create new instance of class " << type << ": " << endl;
209 *fLog << " - Class has no default constructor." << endl;
210 *fLog << " - An abstract member functions of a base class is not overwritten." << endl;
211 return 0;
212 }
213
214 m->SetPosition(pos);
215 m->SetNorm(norm);
216 m->SetShape(shape);
217 m->SetFocalLength(F);
218 m->SetSigmaPSF(psf>=0 ? psf : defpsf);
219
220 if (m->ReadM(arr)>=0)
221 return m;
222
223 *fLog << err << "ERROR - " << type << "::ReadM failed." << endl;
224
225 delete m;
226 return 0;
227}
228
229// --------------------------------------------------------------------------
230//
231// Read a reflector setup from a file. This needs improvemtn.
232//
233// The file structur is like:
234//
235// x y z nx ny nz F [psf] Type ...
236//
237// x: x-coordinate of the mirror's center
238// y: y-coordinate of the mirror's center
239// z: z-coordinate of the mirror's center
240// nx: x-component of the normal vecor in the mirror center
241// ny: y-component of the normal vecor in the mirror center
242// nz: z-component of the normal vecor in the mirror center
243// [shape]: S for spherical <default>, P for parabolic
244// F: Focal distance of a spherical mirror
245// [psf]: This number is the psf given in the units of x,y,z and
246// defined at the focal distance F. It can be used to overwrite
247// the second argument given in ReadFile for individual mirrors.
248// Type: A instance of a mirrot of the class Type MMirrorType is created
249// (Type can be, for example, Hex for for MMirrorHex).
250// ...: Additional arguments as defined in MMirrorType::ReadM
251//
252//
253// Coordinate System:
254// The coordinate system is local in the reflectors frame.
255// It is defined viewing from the back side of the reflector
256// towards the camera. (x "right", y "up", z from reflector to camera)
257// Note, that it is left-handed!
258//
259Bool_t MReflector::ReadFile(TString fname, Double_t defpsf)
260{
261 SetTitle(fname);
262 fMirrors.Delete();
263
264 gSystem->ExpandPathName(fname);
265
266 ifstream fin(fname);
267 if (!fin)
268 {
269 *fLog << err << "Cannot open file " << fname << ": ";
270 *fLog << (errno!=0?strerror(errno):"Insufficient memory for decompression") << endl;
271 return kFALSE;
272 }
273
274/*
275 Int_t idx[964];
276 Int_t srt[964];
277 for (int i=0; i<964; i++)
278 srt[i] = gRandom->Integer(964);
279
280 TMath::Sort(964, srt, idx);
281 */
282
283 Int_t cnt = 0;
284
285 while (1)
286 {
287 TString line;
288 line.ReadLine(fin);
289 if (!fin)
290 break;
291
292 // Count lines
293 cnt++;
294
295 // Skip comments
296 if (line.BeginsWith("#"))
297 continue;
298
299 // Remove leading and trailing whitespaces
300 line=line.Strip(TString::kBoth);
301
302 // Skip empty lines
303 if (line.IsNull())
304 continue;
305
306 // Tokenize line
307 TObjArray *arr = line.Tokenize(' ');
308
309 // Evaluate tokens
310 MMirror *m = EvalTokens(*arr, defpsf);
311
312 // Delete now obsolete array
313 delete arr;
314
315 // Check if a new mirror could be created successfully
316 if (!m)
317 {
318 *fLog << err << "Error in line " << cnt << ": " << line << endl;
319 return kFALSE;
320 }
321
322 // Add new mirror to array
323 fMirrors.Add(m);
324 }
325
326 InitMaxR();
327
328 return kTRUE;
329
330// fMirrors.Sort();
331/*
332 for (int i=0; i<964; i++)
333 {
334 MMirror &ref = (MMirror&)*fMirrors[i];
335
336 TArrayD dist(964);
337 for (int j=0; j<964; j++)
338 {
339 const MMirror &mir = (MMirror&)*fMirrors[j];
340 dist[j] = (ref-mir).Mod();
341 }
342
343 TArrayI idx(964);
344 TMath::Sort(964, dist.GetArray(), idx.GetArray(), kFALSE);
345
346 for (int j=0; j<964; j++)
347 {
348 ref.fNeighbors.Add(fMirrors[idx[j]]);
349 }
350 }*/
351}
352
353// ------------------------------------------------------------------------
354//
355Bool_t MReflector::WriteFile(TString fname) const
356{
357 gSystem->ExpandPathName(fname);
358
359 ofstream fout(fname);
360 if (!fout)
361 {
362 *fLog << err << "Cannot open file " << fname << ": ";
363 *fLog << (errno!=0?strerror(errno):"Insufficient memory for decompression") << endl;
364 return kFALSE;
365 }
366
367 TIter Next(&fMirrors);
368 MMirror *m = 0;
369 while ((m=static_cast<MMirror*>(Next())))
370 {
371 // x: x-coordinate of the mirror's center
372 // y: y-coordinate of the mirror's center
373 // z: z-coordinate of the mirror's center
374 // nx: x-component of the normal vecor in the mirror center
375 // ny: y-component of the normal vecor in the mirror center
376 // nz: z-component of the normal vecor in the mirror center
377 // [shape]: S for spherical <default>, P for parabolic
378 // F: Focal distance of a spherical mirror
379 // [psf]: This number is the psf given in the units of x,y,z and
380 // defined at the focal distance F. It can be used to overwrite
381 // the second argument given in ReadFile for individual mirrors.
382 // Type: A instance of a mirrot of the class Type MMirrorType is created
383 // (Type can be, for example, Hex for for MMirrorHex).
384 // ...: Additional arguments as defined in MMirrorType::ReadM
385
386 fout << setw(12) << m->X() << " ";
387 fout << setw(12) << m->Y() << " ";
388 fout << setw(12) << m->Z() << " ";
389 fout << setw(12) << m->Nx() << " ";
390 fout << setw(12) << m->Ny() << " ";
391 fout << setw(12) << m->Nz() << " ";
392 if (m->GetShape()==1)
393 fout << "P ";
394 fout << m->GetFocalLength() << " ";
395 // cout << m->GetSigmaPSF() << " ";
396 fout << m->ClassName()+7 << " ";
397 m->WriteM(fout);
398 fout << endl;
399 }
400 return kTRUE;
401}
402
403// --------------------------------------------------------------------------
404//
405// Print the collection of mirrors
406//
407void MReflector::Print(Option_t *o) const
408{
409 *fLog << all << GetDescriptor() << " (" << GetNumMirrors() << "): " << endl;
410
411 fMirrors.Print(o);
412}
413
414// --------------------------------------------------------------------------
415//
416// Paint the collection of mirrors
417//
418void MReflector::Paint(Option_t *o)
419{
420 if (!TString(o).Contains("same", TString::kIgnoreCase))
421 MH::SetPadRange(-fMaxR*1.01, -fMaxR*1.01, fMaxR*1.01, fMaxR*1.01);
422
423 fMirrors.Paint(o);
424
425 TEllipse e;
426 e.SetFillStyle(0);
427 e.SetLineColor(17);
428 e.PaintEllipse(0, 0, fMaxR, fMaxR, 0, 360, 0);
429}
430
431// --------------------------------------------------------------------------
432//
433// SigmaPSF: -1
434// FileName: reflector.txt
435//
436// SigmaPSF can be used to set a default for the psf of the mirrors
437// read from the file. Note, that this can be overwritten for individual
438// mirrors in the file. The SigmaPSF is the sigma of a 1D-Gauss fitted
439// to the radial profile of the light distribution.
440//
441// For details on the file structure see MReflector::ReadFile
442//
443Int_t MReflector::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
444{
445 Bool_t rc = kFALSE;
446
447 Double_t psf = -1;
448 if (IsEnvDefined(env, prefix, "SetSigmaPSF", print))
449 {
450 rc = kTRUE;
451 psf = GetEnvValue(env, prefix, "SetSigmaPSF", -1);
452 }
453
454 if (IsEnvDefined(env, prefix, "FileName", print))
455 {
456 rc = kTRUE;
457 if (!ReadFile(GetEnvValue(env, prefix, "FileName", ""), psf))
458 return kERROR;
459 }
460
461 return rc;
462}
Note: See TracBrowser for help on using the repository browser.