source: trunk/Mars/msimreflector/MReflector.cc@ 20048

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