/* ======================================================================== *\ ! ! * ! * This file is part of MARS, the MAGIC Analysis and Reconstruction ! * Software. It is distributed to you in the hope that it can be a useful ! * and timesaving tool in analysing Data of imaging Cerenkov telescopes. ! * It is distributed WITHOUT ANY WARRANTY. ! * ! * Permission to use, copy, modify and distribute this software and its ! * documentation for any purpose is hereby granted without fee, ! * provided that the above copyright notice appear in all copies and ! * that both that copyright notice and this permission notice appear ! * in supporting documentation. It is provided "as is" without express ! * or implied warranty. ! * ! ! Author(s): Wolfgang Wittek 07/2004 ! ! Copyright: MAGIC Software Development, 2000-2004 ! ! \* ======================================================================== */ ///////////////////////////////////////////////////////////////////////////// // // MTelAxisFromStars // // This task // - determines the transformation from expected positions of stars // in the camera to measured positions of these stars in the camera // - applies this transformation to expected positions of other objects // to obtain the estimated positions of these objects in the camera // - puts the estimated positions into the relevant containers // // Input Containers : // MStarCam[MStarCam], MStarCamSource[MStarCam] // // Output Containers : // MSkyCamTrans, MSrcPosCam // ///////////////////////////////////////////////////////////////////////////// #include #include #include #include #include "MTelAxisFromStars.h" #include "MParList.h" #include "MLog.h" #include "MLogManip.h" #include "MReportDrive.h" #include "MPointingPos.h" #include "MSrcPosCam.h" #include "MStarCam.h" #include "MStarPos.h" #include "MSkyCamTrans.h" #include "MStarCamTrans.h" ClassImp(MTelAxisFromStars); using namespace std; // -------------------------------------------------------------------------- // // Constructor // MTelAxisFromStars::MTelAxisFromStars(const char *name, const char *title) { fName = name ? name : "MTelAxisFromStars"; fTitle = title ? title : "Calculate source position from star positions"; // if scale factor fLambda should NOT be fixed set fFixdScaleFactor to // -1.0; otherwise set it to the value requested fFixedScaleFactor = 1.0; // if rotation angle fAlfa should NOT be fixed set fFixdRotationAngle to // -1.0; otherwise set it to the requested value fFixedRotationAngle = 0.0; // default type of input is : the result of the Gauss fit // type 0 : result from the weighted average // type 1 : result from the Gauss fit fInputType = 1; // default value of fAberr // the value 1.07 is valid if the expected position (with aberration) // in the camera is calculated as the average of the positions obtained // from the reflections at the individual mirrors fAberr = 1.07; } // -------------------------------------------------------------------------- // // Destructor // MTelAxisFromStars::~MTelAxisFromStars() { delete fStarCamTrans; } // -------------------------------------------------------------------------- // // Set links to containers // Int_t MTelAxisFromStars::PreProcess(MParList *pList) { fDrive = (MReportDrive*)pList->FindObject(AddSerialNumber("MReportDrive")); if (!fDrive) { *fLog << err << AddSerialNumber("MReportDrive") << " not found... aborting." << endl; return kFALSE; } fStarCam = (MStarCam*)pList->FindObject("MStarCam", "MStarCam"); if (!fStarCam) { *fLog << err << "MStarCam not found... aborting." << endl; return kFALSE; } fSourceCam = (MStarCam*)pList->FindObject("MSourceCam", "MStarCam"); if (!fSourceCam) { *fLog << warn << "MSourceCam[MStarCam] not found... continue " << endl; } //----------------------------------------------------------------- fSrcPos = (MSrcPosCam*)pList->FindCreateObj(AddSerialNumber("MSrcPosCam"), "MSrcPosCam"); if (!fSrcPos) return kFALSE; fPntPos = (MSrcPosCam*)pList->FindCreateObj(AddSerialNumber("MSrcPosCam"), "MPntPosCam"); if (!fPntPos) return kFALSE; fPointPos = (MPointingPos*)pList->FindCreateObj(AddSerialNumber("MPointingPos"), "MPointingPos"); if (!fPointPos) return kFALSE; fSourcePos = (MPointingPos*)pList->FindCreateObj(AddSerialNumber("MPointingPos"), "MSourcePos"); if (!fSourcePos) return kFALSE; fSkyCamTrans = (MSkyCamTrans*)pList->FindCreateObj(AddSerialNumber("MSkyCamTrans")); if (!fSkyCamTrans) return kFALSE; //----------------------------------------------------------------- // book an MStarCamTrans object // this is needed when calling one of the member functions of MStarCamTrans MGeomCam *geom = (MGeomCam*)pList->FindObject(AddSerialNumber("MGeomCam")); if (!geom) { *fLog << err << AddSerialNumber("MGeomCam") << " not found... aborting." << endl; return kFALSE; } MObservatory *obs = (MObservatory*)pList->FindObject(AddSerialNumber("MObservatory")); if (!obs) { *fLog << err << AddSerialNumber("MObservatory") << " not found... aborting." << endl; return kFALSE; } //----------------------------------------------------------------- fStarCamTrans = new MStarCamTrans(*geom, *obs); *fLog << all << "MTelAxisFromStars::Preprocess; the optical aberration factor is set equal to : " << fAberr ; *fLog << all << "MTelAxisFromStars::Preprocess; input type is set equal to : " << fInputType ; if (fInputType == 0) *fLog << " (calculated star positions)" << endl; else *fLog << " (fitted star positions)" << endl; *fLog << all << "MTelAxisFromStars::Preprocess; scale factor will be fixed at : " << fFixedScaleFactor << endl; *fLog << all << "MTelAxisFromStars::Preprocess; rotation angle will be fixed at : " << fFixedRotationAngle << endl; return kTRUE; } // -------------------------------------------------------------------------- // // Set optical aberration factor // // fAberr is the ratio between // the distance from the camera center with optical aberration and // the distance from the camera center with an ideal imaging // // fAberr = r_real/r_ideal // void MTelAxisFromStars::SetOpticalAberr(Double_t aberr) { fAberr = aberr; } // -------------------------------------------------------------------------- // // Set the type of the input // // type = 0 calculated star positions (by averaging) // type = 1 fitted star positions (by Gauss fit) // void MTelAxisFromStars::SetInputType(Int_t type) { fInputType = type; } // -------------------------------------------------------------------------- // // Fix the scale factor fLambda // // void MTelAxisFromStars::FixScaleFactorAt(Double_t lambda) { fFixedScaleFactor = lambda; } // -------------------------------------------------------------------------- // // Fix rotation angle fAlfa // // void MTelAxisFromStars::FixRotationAngleAt(Double_t alfa) { fFixedRotationAngle = alfa; // [degrees] } // -------------------------------------------------------------------------- // // Process // // call FindSkyCamTrans to find the Sky-Camera transformation // call TransSkyCam to transform some sky directions // into the camera system // put the estimated source position into MSrcPosCam // Int_t MTelAxisFromStars::Process() { //Int_t run = fRun->GetRunNumber(); //*fLog << "MTelAxisFromStars::Process; run = " << run << endl; //-------------------------------------- // Define the input for FindSkyCamTrans // // get the expected (axy[0], axy[1]) and the measured positions // (bxy[0], bxy[1]) of stars in the camera from MStarCam Int_t fNumStars = fStarCam->GetNumStars(); if (fNumStars <= 0) return kTRUE; TArrayD axy[2]; axy[0].Set(fNumStars); axy[1].Set(fNumStars); TArrayD bxy[2]; bxy[0].Set(fNumStars); bxy[1].Set(fNumStars); // error matrix of bxy TArrayD exy[2][2]; exy[0][0].Set(fNumStars); exy[0][1].Set(fNumStars); exy[1][0].Set(fNumStars); exy[1][1].Set(fNumStars); // transformation parameters Double_t fLambda; Double_t fAlfa; Double_t fA[2][2]; Double_t fD[2]; Double_t fErrD[2][2]; Int_t fNumIter; Int_t fNdof; Double_t fChi2; Double_t fChi2Prob; MStarPos *star = 0; TIter next(fStarCam->GetList()); Int_t ix = 0; // loop over all stars while ( (star = (MStarPos*)next()) ) { axy[0][ix] = star->GetXExp(); axy[1][ix] = star->GetYExp(); if (fInputType == 0) { // values from averaging bxy[0][ix] = star->GetMeanXCalc(); bxy[1][ix] = star->GetMeanYCalc(); // this is the error matrix for (MeanXCalc, MeanYCalc); // this is the error matrix which should be used exy[0][0][ix] = star->GetXXErrCalc(); exy[0][1][ix] = star->GetXYErrCalc(); exy[1][0][ix] = star->GetXYErrCalc(); exy[1][1][ix] = star->GetYYErrCalc(); //exy[0][0][ix] = star->GetSigmaXCalc()*star->GetSigmaXCalc(); //exy[0][1][ix] = 0.0; //exy[1][0][ix] = 0.0; //exy[1][1][ix] = star->GetSigmaYCalc()*star->GetSigmaYCalc(); } else if (fInputType == 1) { // values from Gauss fit bxy[0][ix] = star->GetMeanXFit(); bxy[1][ix] = star->GetMeanYFit(); // this is the error matrix for (MeanXFit, MeanYFit); // this is the error matrix which should be used exy[0][0][ix] = star->GetXXErrFit(); exy[0][1][ix] = star->GetXYErrFit(); exy[1][0][ix] = star->GetXYErrFit(); exy[1][1][ix] = star->GetYYErrFit(); // this is the error matrix constructed from SigmaXFit and SigmaYFit; // it is used because the errors above are too small, at present //exy[0][0][ix] = star->GetSigmaXFit() * star->GetSigmaXFit(); //exy[0][1][ix] = star->GetCorrXYFit() * // star->GetSigmaXFit() * star->GetSigmaYFit(); //exy[1][0][ix] = exy[0][1][ix]; //exy[1][1][ix] = star->GetSigmaYFit() * star->GetSigmaYFit(); } else { *fLog << err << "MTelAxisFromStars::Process; type of input is not defined" << endl; return kFALSE; } // don't include stars with undefined error Double_t deter = exy[0][0][ix]*exy[1][1][ix] - exy[0][1][ix]*exy[1][0][ix]; //*fLog << "ix ,deter, xx, xy, yy = " << ix << ": " // << deter << ", " << exy[0][0][ix] << ", " // << exy[0][1][ix] << ", " << exy[1][1][ix] << endl; if (deter <= 0.0) continue; //*fLog << "MTelAxisFromStars : " << endl; //*fLog << " ix, XExp, YExp, XFit, YFit, SigmaX2, SigmaXY, SigmaY2 = " // << ix << " : " // << axy[0][ix] << ", " << axy[1][ix] << ", " // << bxy[0][ix] << ", " << bxy[1][ix] << ", " // << exy[0][0][ix] << ", " << exy[0][1][ix] << ", " // << exy[1][1][ix] << endl; ix++; } //-------------------------------------- // Find the transformation from expected positions (axy[1], axy[2]) // to measured positions (bxy[1], bxy[2]) in the camera Int_t fNStars = ix; if (ix < fNumStars) { // reset the sizes of the arrays Int_t fNStars = ix; axy[0].Set(fNStars); axy[1].Set(fNStars); bxy[0].Set(fNStars); bxy[1].Set(fNStars); exy[0][0].Set(fNStars); exy[0][1].Set(fNStars); exy[1][0].Set(fNStars); exy[1][1].Set(fNStars); } Bool_t fitOK; if (fNStars < 1) { //*fLog << "MTelAxisFromStars::Process; no star for MTelAxisFromStars" // << endl; fitOK = kFALSE; } else { fitOK = FindSkyCamTrans(axy, bxy, exy, fFixedRotationAngle, fFixedScaleFactor, fLambda, fAlfa , fA, fD, fErrD, fNumIter, fNdof, fChi2, fChi2Prob); } if (!fitOK && fNStars >= 1) { *fLog << err << "MTelAxisFromStars::Process; Fit to find transformation from star to camera system failed" << endl; //if (fNStars > 0) //{ // *fLog << err // << " fNumIter, fNdof, fChi2, fChi2Prob = " << fNumIter // << ", " << fNdof << ", " << fChi2 << ", " << fChi2Prob << endl; //} return kTRUE; } //-------------------------------------- // Put the transformation parameters into the MSkyCamTrans container fSkyCamTrans->SetParameters(fLambda, fAlfa, fA, fD, fErrD, fNumStars, fNumIter, fNdof, fChi2, fChi2Prob); fSkyCamTrans->SetReadyToSave(); //-------------------------------------- // Put the camera position (X, Y) // obtained by transforming the camera center (0, 0) // into MPntPosCam[MSrcPosCam] fPntPos->SetXY(fD[0], fD[1]); fPntPos->SetReadyToSave(); //-------------------------------------- // Put the corrected pointing position into MPointingPos // SetPointingPosition(fStarCamTrans, fDrive, fSkyCamTrans, fPointPos); //-------------------------------------- // Put the estimated position of the source into SrcPosCam // // get the source direction from MReportDrive // Note : this has to be changed for the wobble mode, where the source // isn't in the center of the camera Double_t decsource = fDrive->GetDec(); Double_t rasource = fDrive->GetRa(); // Double_t radrive = fDrive->GetRa(); Double_t hdrive = fDrive->GetHa(); Double_t hsource = hdrive + radrive - rasource; fSourcePos->SetSkyPosition(rasource, decsource, hsource); SetSourcePosition(fStarCamTrans, fPointPos, fSourcePos, fSrcPos); //*fLog << "after calling SetSourcePosition : , X, Y ,fD = " // << fSrcPos->GetX() << ", " << fSrcPos->GetY() << ", " // << fD[0] << ", " << fD[1] << endl; //-------------------------------------- // Apply the transformation to some expected positions (asxy[1], asxy[2]) // to obtain estimated positions (bsxy[1], bsxy[2]) in the camera // and their error matrices esxy[2][2] // get the expected positions (asxy[1], asxy[2]) from another MStarCam // container (with the name "MSourceCam") Int_t fNumStarsSource = 0; if (fSourceCam) fNumStarsSource = fSourceCam->GetNumStars(); //*fLog << "MTelAxisFromStars::Process; fNumStarsSource = " // << fNumStarsSource << endl; if (fNumStarsSource > 0) { TArrayD asxy[2]; asxy[0].Set(fNumStarsSource); asxy[1].Set(fNumStarsSource); TArrayD bsxy[2]; bsxy[0].Set(fNumStarsSource); bsxy[1].Set(fNumStarsSource); TArrayD esxy[2][2]; esxy[0][0].Set(fNumStarsSource); esxy[0][1].Set(fNumStarsSource); esxy[1][0].Set(fNumStarsSource); esxy[1][1].Set(fNumStarsSource); MStarPos *starSource = 0; TIter nextSource(fSourceCam->GetList()); ix = 0; while ( (starSource = (MStarPos*)nextSource()) ) { asxy[0][ix] = starSource->GetXExp(); asxy[1][ix] = starSource->GetYExp(); ix++; } TransSkyCam(fLambda, fA, fD, fErrD, asxy, bsxy, esxy); // put the estimated positions into the MStarCam container // with name "MSourceCam" TIter setnextSource(fSourceCam->GetList()); ix = 0; while ( (starSource = (MStarPos*)setnextSource()) ) { Double_t corr = esxy[0][1][ix] / TMath::Sqrt( esxy[0][0][ix] * esxy[1][1][ix] ); if (fInputType == 1) { starSource->SetFitValues(100.0, 100.0, bsxy[0][ix], bsxy[1][ix], TMath::Sqrt(esxy[0][0][ix]), TMath::Sqrt(esxy[1][1][ix]), corr, esxy[0][0][ix], esxy[0][1][ix], esxy[1][1][ix], fChi2, fNdof); } else { starSource->SetCalcValues(100.0, 100.0, bsxy[0][ix], bsxy[1][ix], TMath::Sqrt(esxy[0][0][ix]), TMath::Sqrt(esxy[1][1][ix]), corr, esxy[0][0][ix], esxy[0][1][ix], esxy[1][1][ix]); } ix++; } } //-------------------------------------- return kTRUE; } //--------------------------------------------------------------------------- // // FindSkyCamTrans // // This routine determines the transformation // // ( cos(alfa) -sin(alfa) ) // b = lambda * A * a + d A = ( ) // ^ ^ ^ ( sin(alfa) cos(alfa) ) // | | | // scale rotation shift // factor matrix // // from sky coordinates 'a' (projected onto the camera) to camera // coordinates 'b', using the positions of known stars in the camera. // The latter positions may have been determined by analysing the // DC currents in the different pixels. // // Input : a[2] x and y coordinates of stars projected onto the camera; // they were obtained from (RA, dec) of the stars and // (ThetaTel, PhiTel) and the time of observation; // these are the 'expected positions' of stars in the camera // b[2] 'measured positions' of these stars in the camera; // they may have been obtained from the DC currents // e[2][2] error matrix of b[2] // fixedrotationangle value [in degrees] at which rotation angle // alfa should be fixed; -1 means don't fix // fixedscalefactor value at which scale factor lambda // should be fixed; -1 means don't fix // // Output : lambda, alfadeg, A[2][2], d[2] fit results; // parameters describing the transformation // from 'expected positions' to the 'measured // positions' in the camera // errd[2][2] error matrix of d[2] // fNumIter number of iterations // fNdoF number of degrees of freedom // fChi2 chi-square value // fChi2Prob chi-square probability // // The units are assumed to be // [degrees] for alfadeg // [mm] for a, b, d // [1] for lambda Bool_t MTelAxisFromStars::FindSkyCamTrans( TArrayD a[2], TArrayD b[2], TArrayD e[2][2], Double_t &fixedrotationang, Double_t &fixedscalefac, Double_t &lambda, Double_t &alfadeg, Double_t A[2][2], Double_t d[2], Double_t errd[2][2], Int_t &fNumIter, Int_t &fNdof, Double_t &fChi2, Double_t &fChi2Prob) { Int_t fNumStars = a[0].GetSize(); //*fLog << "MTelAxisFromStars::FindSkyCamTrans; expected and measured positions :" // << endl; for (Int_t ix=0; ix 1.1 ) lambda = 1.1; dlambda = lambda - lambdaold; lambdaold = lambda; //*fLog << "num, denom, lambda, dlambda = " << num // << ", " << denom << ", " << lambda << ", " // << dlambda << endl; } } //------- end of iteration ***************************************** alfadeg = alfa * TMath::RadToDeg(); // calculate error matrix of d[2] errd[0][0] = sumcinv[0][0]; errd[0][1] = sumcinv[0][1]; errd[1][0] = sumcinv[1][0]; errd[1][1] = sumcinv[1][1]; // evaluate quality of fit // calculate chi2 for (Int_t ix=0; ixGetDec(); Double_t hdrive = fdrive->GetHa(); Double_t radrive = fdrive->GetRa(); // this is the estimated position (with optical aberration) in the camera // corresponding to the direction in MReportDrive Double_t Xpoint = (ftrans->GetShiftD())[0]; Double_t Ypoint = (ftrans->GetShiftD())[1]; // get the sky direction corresponding to the position (0,0) in the camera Double_t decpoint = 0.0; Double_t hpoint = 0.0; fstarcamtrans->CelCamToCel0(decdrive, hdrive, Xpoint/fAberr, Ypoint/fAberr, decpoint, hpoint); Double_t rapoint = radrive - hpoint + hdrive; fpointpos->SetSkyPosition(rapoint, decpoint, hpoint); // get the local direction corresponding to the position (0,0) in the camera Double_t thetadrive = fdrive->GetNominalZd(); Double_t phidrive = fdrive->GetNominalAz(); Double_t thetapoint = 0.0; Double_t phipoint = 0.0; fstarcamtrans->LocCamToLoc0(thetadrive, phidrive, Xpoint/fAberr, Ypoint/fAberr, thetapoint, phipoint); fpointpos->SetLocalPosition(thetapoint, phipoint); fpointpos->SetReadyToSave(); //*fLog << "SetPointingPosition : decdrive, hdrive, radrive Xpoint, Ypoint = " // << decdrive << ", " << hdrive << ", " << radrive << ", " // << Xpoint << ", " << Ypoint << endl; //*fLog << "SetPointingPosition : thetadrive, phidrive, thetapoint, phipoint = " // << thetadrive << ", " << phidrive << ", " << thetapoint << ", " // << phipoint << endl; return kTRUE; } // -------------------------------------------------------------------------- // // SetSourcePosition // // put the estimated position of the source in the camera into // MSrcPosCam[MSrcPosCam] // // and the estimated local direction of the source into // MSourcePos[MPointingPos] // Bool_t MTelAxisFromStars::SetSourcePosition(MStarCamTrans *fstarcamtrans, MPointingPos *fpointpos, MPointingPos *fsourcepos, MSrcPosCam *fsrcpos) { // get the corrected pointing direction // corresponding to the position (0,0) in the camera Double_t decpoint = fpointpos->GetDec(); Double_t hpoint = fpointpos->GetHa(); // get the sky direction of the source Double_t decsource = fsourcepos->GetDec(); Double_t hsource = fsourcepos->GetHa(); // get the estimated position (Xsource, Ysource) of the source in the camera; // this is a position for an ideal imaging, without optical aberration Double_t Xsource = 0.0; Double_t Ysource = 0.0; fstarcamtrans->Cel0CelToCam(decpoint, hpoint, decsource, hsource, Xsource, Ysource); fsrcpos->SetXY(Xsource*fAberr, Ysource*fAberr); fsrcpos->SetReadyToSave(); // get the estimated local direction of the source Double_t thetapoint = fpointpos->GetZd(); Double_t phipoint = fpointpos->GetAz(); Double_t thetasource = 0.0; Double_t phisource = 0.0; fstarcamtrans->Loc0CamToLoc(thetapoint, phipoint, Xsource, Ysource, thetasource, phisource); fsourcepos->SetLocalPosition(thetasource, phisource); fsourcepos->SetReadyToSave(); //*fLog << "SetSourcePosition : decpoint, hpoint, decsource, hsource, Xsource, Ysource = " // << decpoint << ", " << hpoint << ", " << decsource << ", " // << hsource << ", " << Xsource << ", " << Ysource << endl; //*fLog << "SetSourcePosition : thetapoint, phipoint, thetasource, phisource = " // << thetapoint << ", " << phipoint << ", " << thetasource << ", " // << phisource << endl; return kTRUE; } // --------------------------------------------------------------------------