source: trunk/Mars/mpointing/MSrcPosCalc.cc@ 19344

Last change on this file since 19344 was 18565, checked in by tbretz, 8 years ago
Ceres fits files do not provide (yet?) MMcRunHeader, ignore it.
File size: 19.4 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), fMcCorsika(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 /*
339 if (!fMcHeader)
340 {
341 *fLog << err << "MMcRunHeader not found... aborting." << endl;
342 return kFALSE;
343 }*/
344
345 fMcCorsika = 0;
346 if (!fMcHeader || fMcHeader->IsCeres())
347 return kTRUE;
348
349 fMcCorsika = (MMcCorsikaRunHeader*)plist->FindObject("MMcCorsikaRunHeader");
350 if (!fMcCorsika)
351 {
352 *fLog << err << "MMcCorsikaRunHeader not found... aborting." << endl;
353 return kFALSE;
354 }
355
356 // We don't know here if these are gammas
357 //if (fMcHeader->GetReflVersion()>600)
358 // *fLog << inf << "Source position will be calculated from shower and telescope orientation." << endl;
359
360 // Determine Monte Carlo position from Monte Carlo header
361 TVector2 v(0, 0);
362 if (fMcCorsika->GetWobbleMode()>0.5)
363 v.Set(120.*fGeom->GetConvMm2Deg(), 0.);
364 if (fMcCorsika->GetWobbleMode()<-0.5)
365 v.Set(-120.*fGeom->GetConvMm2Deg(), 0.);
366
367 // Set fixed position
368 fFixedPos = v;
369
370 InitFixedPos();
371
372 return kTRUE;
373}
374
375void MSrcPosCalc::CalcResult(const MVector3 &pos0, const MVector3 &pos)
376{
377 // Calculate source position in camera, and convert to mm:
378 TVector2 v = MAstro::GetDistOnPlain(pos0, pos, -fGeom->GetCameraDist()*1000);
379
380 if (fDeviation)
381 v -= fDeviation->GetDevXY()/fGeom->GetConvMm2Deg();
382
383 SetSrcPos(v);
384}
385
386// --------------------------------------------------------------------------
387//
388// Derotate fX/fY by the current rotation angle, set MSrcPosCam
389//
390Int_t MSrcPosCalc::Process()
391{
392 // In off-data mode the position is set to a fixed value
393 // independent of the run type. In fixed-data mode the position
394 // is set to the predefined position converted to mm.
395 if (fMode==kOffData || fMode==kFixed)
396 {
397 SetSrcPos(fFixedPos/fGeom->GetConvMm2Deg());
398 return kTRUE;
399 }
400
401 // If it is a monte carlo run calculate source position from
402 // Monte Carlo headers
403 if (fRunType==MRawRunHeader::kRTMonteCarlo)
404 {
405 // If the reflector version is too old take source position
406 // from the WobbleMode in the header
407 if (fMcHeader && fMcHeader->GetReflVersion()<=600)
408 {
409 SetSrcPos(fFixedPos/fGeom->GetConvMm2Deg());
410 return kTRUE;
411 }
412
413 // If this is ceres data and we have a view cone keep
414 // the source position fixed to the center of the camera
415 if (fMcCorsika && fMcCorsika->HasViewCone())
416 {
417 SetSrcPos();
418 return kTRUE;
419 }
420
421 // If the reflector version was new enough calculate the
422 // source position from shower and telescope orientation
423 // FIXME: Copy fMcEvt to fSourcePos!
424 MVector3 pos0, pos;
425 pos0.SetZdAz(fPointPos->GetZdRad(), fPointPos->GetAzRad());
426 pos.SetZdAz(fMcEvt->GetParticleTheta(), fMcEvt->GetParticlePhi());
427
428 CalcResult(pos0, pos);
429
430 // If it was not ceres due to a bug in the MAGIC MCs
431 // we have to fix the sign of X
432 if (fMcHeader && !fMcHeader->IsCeres())
433 SetSrcPos(TVector2(-fSrcPosCam->GetX(), fSrcPosCam->GetY()));
434
435 return kTRUE;
436 }
437
438 // If the user requested a fixed source position use this position
439 if (!fSourcePos || !fTime || !fObservatory)
440 {
441 SetSrcPos(fFixedPos/fGeom->GetConvMm2Deg());
442 return kTRUE;
443 }
444
445 // Set Sky coordinates of source, taken from container "MSourcePos"
446 // of type MPointingPos. The sky coordinates must be J2000, as the
447 // sky coordinates of the camera center that we get from the container
448 // "MPointingPos" filled by the Drive.
449 MVector3 pos; // pos: source position
450 pos.SetRaDec(fSourcePos->GetRaRad(), fSourcePos->GetDecRad());
451
452 // Set sky coordinates of camera center in pos0 (for details see below)
453 MVector3 pos0; // pos0: camera center
454 pos0.SetRaDec(fPointPos->GetRaRad(), fPointPos->GetDecRad());
455
456 // Here we check that the source position which was given
457 // by the drive system is not off by more than 1deg from the
458 // source position given by the user. (Checking every individual
459 // event is not the fastest, but the safest)
460 if (pos.Angle(pos0)*TMath::RadToDeg()>1)
461 {
462 *fLog << err << "ERROR - Defined source position deviates from pointing-ra/dec by more than 1deg (";
463 *fLog << pos.Angle(pos0) << ")!" << endl;
464 *fLog << "User defined source pos: ";
465 fSourcePos->Print();
466 *fLog << "Pointing position of tel: ";
467 fPointPos->Print();
468
469 return kERROR;
470 }
471
472 // Convert sky coordinates of source to local coordinates. Warning! These are not the "true" local
473 // coordinates, since this transformation ignores precession and nutation effects.
474 const MAstroSky2Local conv(*fTime, *fObservatory);
475 pos *= conv;
476
477 // Convert sky coordinates of camera center convert to local.
478 // Same comment as above. These coordinates differ from the true
479 // local coordinates of the camera center that one could get from
480 // "MPointingPos", calculated by the Drive: the reason is that the Drive
481 // takes into account precession and nutation corrections, while
482 // MAstroSky2Local (as of Jan 27 2005 at least) does not. Since we just
483 // want to get the source position on the camera from the local
484 // coordinates of the center and the source, it does not matter that
485 // the coordinates contained in pos and pos0 ignore precession and
486 // nutation... since the shift would be the same in both cases. What
487 // would be wrong is to set in pos0 directly the local coordinates
488 // found in MPointingPos!
489 pos0 *= conv;
490
491 //TVector2 vx;
492 if (fDeviation)
493 {
494 // Position at which the starguider camera is pointing in real:
495 // pointing position = nominal position - dev
496 //
497 //vx = CalcXYinCamera(pos0, pos)*fGeom->GetCameraDist()*1000;
498 pos0.SetZdAz(pos0.Theta()-fDeviation->GetDevZdRad(),
499 pos0.Phi() -fDeviation->GetDevAzRad());
500 }
501
502 CalcResult(pos0, pos);
503 return kTRUE;
504}
505
506// --------------------------------------------------------------------------
507//
508// Convert a coordinate stored in str into a double, stored in ret.
509// Returns kTRUE on success, otherwise kFALSE
510//
511// Allowed formats are:
512// 12.5
513// -12.5
514// +12.5
515// -12:30:00.0
516// 12:30:00.0
517// +12:30:00.0
518//
519Bool_t MSrcPosCalc::GetCoordinate(TString str, Double_t &ret) const
520{
521 str = str.Strip(TString::kBoth);
522
523 if (str.First(':')<0)
524 {
525 ret = str.Atof();
526 return kTRUE;
527 }
528
529 if (MAstro::Coordinate2Angle(str, ret))
530 return kTRUE;
531
532 *fLog << err << GetDescriptor() << endl;
533 *fLog << "Interpretation of Coordinate '" << str << "' not successfull... abort." << endl;
534 *fLog << "Corrdinate must have the format: '-12:30:00.0', '12:30:00.0' or '+12:30:00.0'" << endl;
535 return kFALSE;
536}
537
538// --------------------------------------------------------------------------
539//
540// Read the setup from a TEnv, eg:
541// MSrcPosCalc.SourceRa: ra
542// MSrcPosCalc.SourceDec: dec
543// MSrcPosCalc.SourcePos: ra dec
544//
545// For format of 'ra' and 'dec' see GetCoordinate()
546//
547// Coordinates are J2000.0
548//
549Int_t MSrcPosCalc::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
550{
551 Bool_t rc = kFALSE;
552
553 if (IsEnvDefined(env, prefix, "FixedPos", print))
554 {
555 TString str = GetEnvValue(env, prefix, "FixedPos", "");
556 str = str.Strip(TString::kBoth);
557
558 Double_t x, y;
559 const Int_t n=sscanf(str.Data(), "%lf %lf", &x, &y);
560 if (n!=2)
561 {
562 *fLog << warn << "WARNING - FixedPos requires two numbers." << endl;
563 return kERROR;
564 }
565
566 fFixedPos = TVector2(x, y);
567 fMode = kFixed;
568
569 rc = kTRUE;
570 }
571
572 Double_t ra=0;
573 Double_t dec=0;
574
575 if (IsEnvDefined(env, prefix, "SourceRaDec", print))
576 {
577 TString str = GetEnvValue(env, prefix, "SourceRaDec", "");
578 str = str.Strip(TString::kBoth);
579
580 const Ssiz_t pos = str.First(' ');
581 if (pos<0)
582 {
583 *fLog << err << GetDescriptor() << "SourceRaDec empty... abort." << endl;
584 return kERROR;
585 }
586
587 if (!GetCoordinate(str(0, pos), ra))
588 return kERROR;
589 if (!GetCoordinate(str(pos+1, str.Length()), dec))
590 return kERROR;
591
592 SetSourcePos(ra, dec);
593 return rc;
594 }
595
596 Bool_t rcsrc = kFALSE;
597 if (IsEnvDefined(env, prefix, "SourceRa", print))
598 {
599 TString str = GetEnvValue(env, prefix, "SourceRa", "");
600
601 if (!GetCoordinate(str, ra))
602 return kERROR;
603
604 rcsrc = kTRUE;
605 }
606
607 if (IsEnvDefined(env, prefix, "SourceDec", print))
608 {
609 TString str = GetEnvValue(env, prefix, "SourceDec", "");
610
611 if (!GetCoordinate(str, dec))
612 return kERROR;
613
614 rcsrc = kTRUE;
615 }
616
617 if (rcsrc)
618 SetSourcePos(ra, dec);
619
620 return rcsrc || rc;
621}
Note: See TracBrowser for help on using the repository browser.