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

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