source: trunk/MagicSoft/Mars/mpointing/MSrcPosCalc.cc@ 9469

Last change on this file since 9469 was 9342, checked in by tbretz, 16 years ago
*** empty log message ***
File size: 18.9 KB
Line 
1/* ======================================================================== *\
2!
3! *
4! * This file is part of MARS, the MAGIC 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 appear 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 3/2004 <mailto:tbretz@astro.uni-wuerzburg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2008
21!
22!
23\* ======================================================================== */
24
25//////////////////////////////////////////////////////////////////////////////
26//
27// MSrcPosCalc
28//
29// Calculate the current source position in the camera from the (possibly
30// already corrected, by starguider) J2000 sky coordinates of the camera
31// center (contained in MPointingPos), and the source J2000 sky
32// coordinates contained in MSourcePos (of type MPointingPos as well). If
33// no MSourcePos is found in the parameter list, source position is
34// assumed to be the same for all events, that specified in MSrcPosCam
35// (if it already existed in the parameter list), or (0,0), the center of
36// the camera, if no MSrcPosCam was present in the parameter list. In both
37// cases, no calculation is necessary and then the PreProcess returns
38// kSKIP so that the task is removed from the task list.
39//
40// The conversion factor between the camera plain (mm) and the sky (deg)
41// is taken from MGeomCam. The time is taken from MTime, and the
42// coordinates of the observatory from MObservatory.
43//
44// If a reflector version >= 700 is detected the source position for
45// Gammas (and _only_ gammas) is dynamically calculated from the
46// telescope (e.g. MMcEvt::fTelescopePhi) and the shower (e.g. MMcEvt::fPhi)
47// orientation. In off-mode it is fixed at the camera center.
48//
49// FIXME: Add here some information about the more-cycle calculation
50//
51// Input Container:
52// MPointingPos
53// MObservatory
54// MGeomCam
55// MTime
56// [MMcRunHeader]
57// [MMcCorsikaRunHeader]
58// [MSourcePos] (of type MPointingPos)
59//
60// Output Container:
61// MSrcPosCam
62//
63// To be done:
64// - a switch between using sky-coordinates and time or local-coordinates
65// from MPointingPos for determine the rotation angle. (Therefor a conversion
66// needs to be implemented inlcuding asrometric corrections)
67//
68// - the center of rotation need not to be the camera center
69///// NOTE, A. Moralejo: I don't see the need for special code either.
70//
71//////////////////////////////////////////////////////////////////////////////
72#include "MSrcPosCalc.h"
73
74#include <TRandom.h>
75#include <TVector2.h>
76
77#include "MParList.h"
78#include "MTaskList.h"
79
80#include "MLog.h"
81#include "MLogManip.h"
82
83#include "MGeomCam.h"
84#include "MObservatory.h"
85#include "MPointingPos.h"
86#include "MPointingDev.h"
87#include "MSrcPosCam.h"
88#include "MRawRunHeader.h"
89
90#include "MMcEvt.hxx"
91#include "MMcRunHeader.hxx"
92#include "MMcCorsikaRunHeader.h"
93
94#include "MAstro.h"
95#include "MVector3.h"
96#include "MAstroSky2Local.h"
97
98ClassImp(MSrcPosCalc);
99
100using namespace std;
101
102// --------------------------------------------------------------------------
103//
104// Initialize fY and fY with 0
105//
106MSrcPosCalc::MSrcPosCalc(const char *name, const char *title)
107 : fObservatory(NULL), fPointPos(NULL), fDeviation(NULL), fMcEvt(NULL),
108 fMcHeader(NULL), fGeom(NULL), fTime(NULL), fCallback(NULL),
109 fSourcePos(NULL), fSrcPosCam(NULL), fSrcPosAnti(NULL), fMode(kDefault),
110 fNumRandomOffPositions(0)
111{
112 fName = name ? name : "MSrcPosCalc";
113 fTitle = title ? title : "Calculates the source position in the camera";
114
115 AddToBranchList("MTime.*");
116 AddToBranchList("MMcEvt.*");
117 AddToBranchList("MPointingPos.*");
118}
119
120// --------------------------------------------------------------------------
121//
122// delete fSourcePos if kIsOwner
123// set fSourcePos to NULL
124//
125void MSrcPosCalc::FreeSourcePos()
126{
127 if (fSourcePos && TestBit(kIsOwner))
128 delete fSourcePos;
129
130 fSourcePos = NULL;
131}
132
133// --------------------------------------------------------------------------
134//
135// ra [h]
136// dec [deg]
137//
138void MSrcPosCalc::SetSourcePos(Double_t ra, Double_t dec)
139{
140 FreeSourcePos();
141
142 fSourcePos = new MPointingPos("MSourcePos");
143 fSourcePos->SetSkyPosition(ra, dec);
144
145 SetOwner();
146}
147
148// --------------------------------------------------------------------------
149//
150// Return ra/dec as string
151//
152TString MSrcPosCalc::GetRaDec(const MPointingPos &pos) const
153{
154 const TString rstr = MAstro::Angle2Coordinate(pos.GetRa());
155 const TString dstr = MAstro::Angle2Coordinate(pos.GetDec());
156
157 return Form("Ra=%sh Dec=%sdeg", rstr.Data(), dstr.Data());
158}
159
160// --------------------------------------------------------------------------
161//
162// Search and if necessary create MSrcPosCam in the parameter list. Search
163// MSourcePos. If not found, do nothing else, and skip the task. If MSrcPosCam
164// did not exist before and has been created here, it will contain as source
165// position the camera center (0,0).
166// In the case that MSourcePos is found, go ahead in searching the rest of
167// necessary containers. The source position will be calculated for each
168// event in Process.
169//
170Int_t MSrcPosCalc::PreProcess(MParList *pList)
171{
172 // Reset fixed position
173 fFixedPos = TVector2();
174
175 fSrcPosCam = (MSrcPosCam*)pList->FindCreateObj("MSrcPosCam");
176 if (!fSrcPosCam)
177 return kFALSE;
178
179 fSrcPosAnti = (MSrcPosCam*)pList->FindCreateObj("MSrcPosCam", "MSrcPosAnti");
180 if (!fSrcPosAnti)
181 return kFALSE;
182
183 fGeom = (MGeomCam*)pList->FindObject("MGeomCam");
184 if (!fGeom)
185 {
186 *fLog << err << "MGeomCam not found... aborting." << endl;
187 return kFALSE;
188 }
189
190 fPointPos = (MPointingPos*)pList->FindObject("MPointingPos");
191 if (!fPointPos)
192 {
193 *fLog << err << "MPointingPos not found... aborting." << endl;
194 return kFALSE;
195 }
196
197 if (!fSourcePos)
198 {
199 fSourcePos = (MPointingPos*)pList->FindObject("MSourcePos", "MPointingPos");
200 if (!fSourcePos)
201 {
202 *fLog << inf;
203 *fLog << "MSourcePos [MPointPos] not found... The source position" << endl;
204 *fLog << "set in MSrcPosCam will be set to (0/0) or in the case" << endl;
205 *fLog << "of Monte Carlo set to the appropriate wobble position." << endl;
206 return kTRUE;
207 }
208 }
209 // FIXME: Maybe we have to call FreeSourcePos in PostProcess()?
210
211 fDeviation = (MPointingDev*)pList->FindObject("MPointingDev");
212
213 *fLog << inf;
214 //*fLog << "Pointing Position: " << GetRaDec(*fPointPos) << endl;
215 *fLog << "Source Position: " << GetRaDec(*fSourcePos) << endl;
216 if (fCallback)
217 *fLog << "Calculating " << fCallback->GetNumPasses() << " off-regions." << endl;
218 if (fNumRandomOffPositions)
219 *fLog << "Calculating " << fNumRandomOffPositions << " random off-regions." << endl;
220
221 // For the case ReInit is never called we try:
222 fObservatory = (MObservatory*)pList->FindObject("MObservatory");
223 fTime = (MTime*) pList->FindObject("MTime");
224 fRunType = MRawRunHeader::kRTNone;
225
226 return kTRUE;
227}
228
229// --------------------------------------------------------------------------
230//
231// Divide the 360deg into num+1 positions. Rotate the given vector
232// by pass+1 steps and return the result.
233//
234TVector2 MSrcPosCalc::Rotate(TVector2 v, Int_t pass, Int_t num) const
235{
236 const Double_t step = TMath::TwoPi()/(num+1);
237 return v.Rotate(step*(pass+1));
238}
239
240// --------------------------------------------------------------------------
241//
242// If fIsWobbleMode==kFALSE set source position to v and anto-source
243// position to -v, if fIsWobbleMode==kTRUE vice versa.
244//
245void MSrcPosCalc::SetSrcPos(TVector2 v) const
246{
247 if (fMode==kWobble)
248 {
249 // The trick here is that the anti-source position in case
250 // of the off-source regions is always the on-source positon
251 // thus a proper anti-source cut is possible.
252 fSrcPosAnti->SetXY(v);
253 if (fCallback)
254 v = Rotate(v, fCallback->GetNumPass(), fCallback->GetNumPasses());
255 else
256 v *= -1;
257 fSrcPosCam->SetXY(v);
258 }
259 else
260 {
261 // Because we don't process this three times like in the
262 // wobble case we have to find another way to determine which
263 // off-source region is the right anti-source position
264 // We do it randomly.
265 fSrcPosCam->SetXY(v);
266 if (fNumRandomOffPositions>1)
267 v = Rotate(v, gRandom->Integer(fNumRandomOffPositions), fNumRandomOffPositions);
268 else
269 v *= -1;
270 fSrcPosAnti->SetXY(v);
271 }
272}
273
274void MSrcPosCalc::InitFixedPos() const
275{
276 // It is set here for the cases in which Process is not called at all
277 fSrcPosCam->SetXY(fFixedPos/fGeom->GetConvMm2Deg());
278
279 // Informal message output
280 *fLog << inf;
281 *fLog << "Source position set to x=" << fFixedPos.X() << "deg ";
282 *fLog << "y=" << fFixedPos.Y() << "deg" << endl;
283}
284
285// --------------------------------------------------------------------------
286//
287// Checking for file type. If the file type is Monte Carlo the
288// source position is arbitrarily determined from the MC headers.
289//
290Bool_t MSrcPosCalc::ReInit(MParList *plist)
291{
292 // In OffMode set fixed position to camera center
293 if (fMode==kOffData)
294 fFixedPos = TVector2();
295
296 if (fMode==kOffData || fMode==kFixed)
297 {
298 // It is set here for the cases in which Process is not called at all
299 InitFixedPos();
300 return kTRUE;
301 }
302
303 MRawRunHeader *run = (MRawRunHeader*)plist->FindObject("MRawRunHeader");
304 if (!run)
305 {
306 *fLog << err << "MRawRunHeader not found... aborting." << endl;
307 return kFALSE;
308 }
309
310 fRunType = run->GetRunType();
311
312 if (fRunType!=MRawRunHeader::kRTMonteCarlo)
313 {
314 fObservatory = (MObservatory*)plist->FindObject("MObservatory");
315 if (!fObservatory)
316 {
317 *fLog << err << "MObservatory not found... aborting." << endl;
318 return kFALSE;
319 }
320 fTime = (MTime*)plist->FindObject("MTime");
321 if (!fTime)
322 {
323 *fLog << err << "MTime not found... aborting." << endl;
324 return kFALSE;
325 }
326
327 return kTRUE;
328 }
329
330 fMcEvt = (MMcEvt*)plist->FindObject("MMcEvt");
331 if (!fMcEvt)
332 {
333 *fLog << err << "MMcEvt not found... aborting." << endl;
334 return kFALSE;
335 }
336
337 fMcHeader = (const MMcRunHeader*)plist->FindObject("MMcRunHeader");
338 if (!fMcHeader)
339 {
340 *fLog << err << "MMcRunHeader not found... aborting." << endl;
341 return kFALSE;
342 }
343
344 if (fMcHeader->IsCeres())
345 return kTRUE;
346
347 const MMcCorsikaRunHeader *h = (MMcCorsikaRunHeader*)plist->FindObject("MMcCorsikaRunHeader");
348 if (!h)
349 {
350 *fLog << err << "MMcCorsikaRunHeader not found... aborting." << endl;
351 return kFALSE;
352 }
353
354 // We don't know here if these are gammas
355 //if (fMcHeader->GetReflVersion()>600)
356 // *fLog << inf << "Source position will be calculated from shower and telescope orientation." << endl;
357
358 // Determine Monte Carlo position from Monte Carlo header
359 TVector2 v(0, 0);
360 if (h->GetWobbleMode()>0.5)
361 v.Set(120.*fGeom->GetConvMm2Deg(), 0.);
362 if (h->GetWobbleMode()<-0.5)
363 v.Set(-120.*fGeom->GetConvMm2Deg(), 0.);
364
365 // Set fixed position
366 fFixedPos = v;
367
368 InitFixedPos();
369
370 return kTRUE;
371}
372
373void MSrcPosCalc::CalcResult(const MVector3 &pos0, const MVector3 &pos)
374{
375 // Calculate source position in camera, and convert to mm:
376 TVector2 v = MAstro::GetDistOnPlain(pos0, pos, -fGeom->GetCameraDist()*1000);
377
378 if (fDeviation)
379 v -= fDeviation->GetDevXY()/fGeom->GetConvMm2Deg();
380
381 SetSrcPos(v);
382}
383
384// --------------------------------------------------------------------------
385//
386// Derotate fX/fY by the current rotation angle, set MSrcPosCam
387//
388Int_t MSrcPosCalc::Process()
389{
390 // In off-data mode the position is set to a fixed value
391 // independent of the run type. In fixed-data mode the position
392 // is set to the predefined position converted to mm.
393 if (fMode==kOffData || fMode==kFixed)
394 {
395 SetSrcPos(fFixedPos/fGeom->GetConvMm2Deg());
396 return kTRUE;
397 }
398
399 // If it is a monte carlo run calculate source position from
400 // Monte Carlo headers
401 if (fRunType==MRawRunHeader::kRTMonteCarlo)
402 {
403 // If the reflector version is too old take source position
404 // from the WobbleMode in the header
405 if (fMcHeader->GetReflVersion()<=600)
406 {
407 SetSrcPos(fFixedPos/fGeom->GetConvMm2Deg());
408 return kTRUE;
409 }
410
411 // If the reflector version was new enough calculate the
412 // source position from shower and telescope orientation
413 // FIXME: Copy fMcEvt to fSourcePos!
414 MVector3 pos0, pos;
415 pos0.SetZdAz(fPointPos->GetZdRad(), fPointPos->GetAzRad());
416 pos.SetZdAz(fMcEvt->GetTheta(), fMcEvt->GetPhi());
417
418 CalcResult(pos0, pos);
419 return kTRUE;
420 }
421
422 // If the user requested a fixed source position use this position
423 if (!fSourcePos || !fTime || !fObservatory)
424 {
425 SetSrcPos(fFixedPos/fGeom->GetConvMm2Deg());
426 return kTRUE;
427 }
428
429 // Set Sky coordinates of source, taken from container "MSourcePos"
430 // of type MPointingPos. The sky coordinates must be J2000, as the
431 // sky coordinates of the camera center that we get from the container
432 // "MPointingPos" filled by the Drive.
433 MVector3 pos; // pos: source position
434 pos.SetRaDec(fSourcePos->GetRaRad(), fSourcePos->GetDecRad());
435
436 // Set sky coordinates of camera center in pos0 (for details see below)
437 MVector3 pos0; // pos0: camera center
438 pos0.SetRaDec(fPointPos->GetRaRad(), fPointPos->GetDecRad());
439
440 // Here we check that the source position which was given
441 // by the drive system is not off by more than 1deg from the
442 // source position given by the user. (Checking every individual
443 // event is not the fastest, but the safest)
444 if (pos.Angle(pos0)*TMath::RadToDeg()>1)
445 {
446 *fLog << err << "ERROR - Defined source position deviates from pointing-ra/dec by more than 1deg (";
447 *fLog << pos.Angle(pos0) << ")!" << endl;
448 *fLog << "User defined source pos: ";
449 fSourcePos->Print();
450 *fLog << "Pointing position of tel: ";
451 fPointPos->Print();
452
453 return kERROR;
454 }
455
456 // Convert sky coordinates of source to local coordinates. Warning! These are not the "true" local
457 // coordinates, since this transformation ignores precession and nutation effects.
458 const MAstroSky2Local conv(*fTime, *fObservatory);
459 pos *= conv;
460
461 // Convert sky coordinates of camera center convert to local.
462 // Same comment as above. These coordinates differ from the true
463 // local coordinates of the camera center that one could get from
464 // "MPointingPos", calculated by the Drive: the reason is that the Drive
465 // takes into account precession and nutation corrections, while
466 // MAstroSky2Local (as of Jan 27 2005 at least) does not. Since we just
467 // want to get the source position on the camera from the local
468 // coordinates of the center and the source, it does not matter that
469 // the coordinates contained in pos and pos0 ignore precession and
470 // nutation... since the shift would be the same in both cases. What
471 // would be wrong is to set in pos0 directly the local coordinates
472 // found in MPointingPos!
473 pos0 *= conv;
474
475 //TVector2 vx;
476 if (fDeviation)
477 {
478 // Position at which the starguider camera is pointing in real:
479 // pointing position = nominal position - dev
480 //
481 //vx = CalcXYinCamera(pos0, pos)*fGeom->GetCameraDist()*1000;
482 pos0.SetZdAz(pos0.Theta()-fDeviation->GetDevZdRad(),
483 pos0.Phi() -fDeviation->GetDevAzRad());
484 }
485
486 CalcResult(pos0, pos);
487 return kTRUE;
488}
489
490// --------------------------------------------------------------------------
491//
492// Convert a coordinate stored in str into a double, stored in ret.
493// Returns kTRUE on success, otherwise kFALSE
494//
495// Allowed formats are:
496// 12.5
497// -12.5
498// +12.5
499// -12:30:00.0
500// 12:30:00.0
501// +12:30:00.0
502//
503Bool_t MSrcPosCalc::GetCoordinate(TString str, Double_t &ret) const
504{
505 str = str.Strip(TString::kBoth);
506
507 if (str.First(':')<0)
508 {
509 ret = str.Atof();
510 return kTRUE;
511 }
512
513 if (MAstro::Coordinate2Angle(str, ret))
514 return kTRUE;
515
516 *fLog << err << GetDescriptor() << endl;
517 *fLog << "Interpretation of Coordinate '" << str << "' not successfull... abort." << endl;
518 *fLog << "Corrdinate must have the format: '-12:30:00.0', '12:30:00.0' or '+12:30:00.0'" << endl;
519 return kFALSE;
520}
521
522// --------------------------------------------------------------------------
523//
524// Read the setup from a TEnv, eg:
525// MSrcPosCalc.SourceRa: ra
526// MSrcPosCalc.SourceDec: dec
527// MSrcPosCalc.SourcePos: ra dec
528//
529// For format of 'ra' and 'dec' see GetCoordinate()
530//
531// Coordinates are J2000.0
532//
533Int_t MSrcPosCalc::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
534{
535 Bool_t rc = kFALSE;
536
537 if (IsEnvDefined(env, prefix, "FixedPos", print))
538 {
539 TString str = GetEnvValue(env, prefix, "FixedPos", "");
540 str = str.Strip(TString::kBoth);
541
542 Double_t x, y;
543 const Int_t n=sscanf(str.Data(), "%lf %lf", &x, &y);
544 if (n!=2)
545 {
546 *fLog << warn << "WARNING - FixedPos requires two numbers." << endl;
547 return kERROR;
548 }
549
550 fFixedPos = TVector2(x, y);
551 fMode = kFixed;
552
553 rc = kTRUE;
554 }
555
556 Double_t ra=0;
557 Double_t dec=0;
558
559 if (IsEnvDefined(env, prefix, "SourceRaDec", print))
560 {
561 TString str = GetEnvValue(env, prefix, "SourceRaDec", "");
562 str = str.Strip(TString::kBoth);
563
564 const Ssiz_t pos = str.First(' ');
565 if (pos<0)
566 {
567 *fLog << err << GetDescriptor() << "SourceRaDec empty... abort." << endl;
568 return kERROR;
569 }
570
571 if (!GetCoordinate(str(0, pos), ra))
572 return kERROR;
573 if (!GetCoordinate(str(pos+1, str.Length()), dec))
574 return kERROR;
575
576 SetSourcePos(ra, dec);
577 return rc;
578 }
579
580 Bool_t rcsrc = kFALSE;
581 if (IsEnvDefined(env, prefix, "SourceRa", print))
582 {
583 TString str = GetEnvValue(env, prefix, "SourceRa", "");
584
585 if (!GetCoordinate(str, ra))
586 return kERROR;
587
588 rcsrc = kTRUE;
589 }
590
591 if (IsEnvDefined(env, prefix, "SourceDec", print))
592 {
593 TString str = GetEnvValue(env, prefix, "SourceDec", "");
594
595 if (!GetCoordinate(str, dec))
596 return kERROR;
597
598 rcsrc = kTRUE;
599 }
600
601 if (rcsrc)
602 SetSourcePos(ra, dec);
603
604 return rcsrc || rc;
605}
Note: See TracBrowser for help on using the repository browser.