/* ======================================================================== *\
!
! *
! * 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 expressed
! * or implied warranty.
! *
!
!
!   Author(s): Javier López ,   4/2004 <mailto:jlopez@ifae.es>
!              Robert Wagner,   7/2004 <mailto:rwagner@mppmu.mpg.de>
!              Wolfgang Wittek, 8/2004 <mailto:wittek@mppmu.mpg.de>
!
!   Copyright: MAGIC Software Development, 2000-2004
!
!
\* ======================================================================== */
#include "MStarLocalPos.h"

#include <TEllipse.h>
#include <TMarker.h>

#include "MLog.h"
#include "MLogManip.h"

ClassImp(MStarLocalPos);

using namespace std;

MStarLocalPos::MStarLocalPos(const char *name, const char *title)
{

    fName  = name  ? name  : "MStarLocalPos";
    fTitle = title ? title : "";
    
    Reset();
}

void MStarLocalPos::Reset()
{

    //Expected position on camera
     fMagExp = 0.;
     fXExp = 0.;
     fYExp = 0.;

    //Info from calculation
     fMagCalc = 0.;
     fMaxCalc = 0.;
     fMeanXCalc = 0.;
     fMeanYCalc = 0.;
     fSigmaMinorAxisCalc = 0.;
     fSigmaMajorAxisCalc = 0.;

    //Info from uncorrelated Gauss fit
     fMagFit = 0.;
     fMaxFit = 0.;
     fMeanXFit = 0.;
     fMeanYFit = 0.;
     fSigmaMinorAxisFit = 0.;
     fSigmaMajorAxisFit = 0.;

     fChiSquare = 0.;
     fNdof = 1;

    //Info from correlated Gauss fit
     fMagCGFit    = 0.;
     fMaxCGFit    = 0.;
     fMeanXCGFit  = 0.;
     fMeanYCGFit  = 0.;
     fSigmaXCGFit = 0.;
     fSigmaYCGFit = 0.;
     fCorrXYCGFit = 0.;
     fXXErrCGFit  = 0.;
     fXYErrCGFit  = 0.;
     fYYErrCGFit  = 0.;

     fChiSquareCGFit = 0.;
     fNdofCGFit      = 1;

}

void MStarLocalPos::SetExpValues(Float_t mag, Float_t x, Float_t y)
{
     fMagExp = mag;
     fXExp = x;
     fYExp = y;
}

void MStarLocalPos::SetIdealValues(Float_t mag, Float_t x, Float_t y)
{
     fMagIdeal = mag;
     fXIdeal = x;
     fYIdeal = y;
}

void MStarLocalPos::SetCalcValues(Float_t mag, Float_t max, 
        Float_t x, Float_t y, Float_t sigmaMinorAxis, Float_t sigmaMajorAxis)
{
     fMagCalc = mag;
     fMaxCalc = max;
     fMeanXCalc = x;
     fMeanYCalc = y;
     fSigmaMinorAxisCalc = sigmaMinorAxis;
     fSigmaMajorAxisCalc = sigmaMajorAxis;
}

void MStarLocalPos::SetFitValues(Float_t mag, Float_t max, 
        Float_t x, Float_t y, Float_t sigmaMinorAxis, Float_t sigmaMajorAxis, 
        Float_t chiSquare, Int_t ndof)
{
     fMagFit = mag;
     fMaxFit = max;
     fMeanXFit = x;
     fMeanYFit = y;
     fSigmaMinorAxisFit = sigmaMinorAxis;
     fSigmaMajorAxisFit = sigmaMajorAxis;
     fChiSquare = chiSquare;
     fNdof = ndof;
}

void MStarLocalPos::SetFitValues(Float_t mag, Float_t max, 
        Float_t x, Float_t y, Float_t sigmaMinorAxis, Float_t sigmaMajorAxis, 
        Float_t chiSquare, Int_t ndof, 
        Float_t xx, Float_t xy, Float_t yy)
{
  SetFitValues(mag, max, x, y, sigmaMinorAxis, sigmaMajorAxis, chiSquare, ndof);
  fXXErr = xx;
  fYYErr = yy;
  fXYErr = xy;
}

void MStarLocalPos::SetCGFitValues(
               Float_t mag,       Float_t max,    Float_t x,    Float_t y, 
               Float_t sigmaX,    Float_t sigmaY, Float_t correlation, 
               Float_t xx,        Float_t xy,     Float_t yy,
               Float_t chiSquare, Int_t ndof)
{
     fMagCGFit    = mag;
     fMaxCGFit    = max;
     fMeanXCGFit  = x;
     fMeanYCGFit  = y;
     fSigmaXCGFit = sigmaX;
     fSigmaYCGFit = sigmaY;
     fCorrXYCGFit = correlation;
     fXXErrCGFit  = xx;
     fXYErrCGFit  = xy;
     fYYErrCGFit  = yy;

     fChiSquareCGFit = chiSquare;
     fNdofCGFit      = ndof;
}


// --------------------------------------------------------------------------
//
// Paint the ellipse corresponding to the parameters
//
void MStarLocalPos::Paint(Option_t *opt)
{
  //Print a cross in the expected position
  TMarker mexp(fXExp, fYExp, 29);
  mexp.SetMarkerSize(3);
  mexp.SetMarkerColor(94);
  mexp.Paint(); 

  if (fSigmaMinorAxisCalc>0. && fSigmaMajorAxisCalc>0.)
    {
      TEllipse ecalc(fMeanXCalc, fMeanYCalc, fSigmaMinorAxisCalc, fSigmaMajorAxisCalc, 0, 360, 0);
      ecalc.SetLineWidth(3);
      ecalc.SetLineColor(kBlue);
      ecalc.Paint();
    }

  if (fSigmaMinorAxisFit>0. && fSigmaMajorAxisFit>0.)
    {
      TEllipse efit(fMeanXFit, fMeanYFit, fSigmaMinorAxisFit, fSigmaMajorAxisFit, 0, 360, 0);
      efit.SetLineWidth(3);
      efit.SetLineColor(kBlack);
      efit.Paint();
    }

  if (fSigmaXCGFit>0. && fSigmaYCGFit>0.)
    {
      //Print a cross in the fitted position
      //TMarker mCGFit(fMeanXCGFit, fMeanYCGFit, 3);
      //mCGFit.SetMarkerSize(3);
      //mCGFit.SetMarkerColor(1);
      //mCGFit.Paint(); 

      Double_t cxx = fSigmaXCGFit*fSigmaXCGFit;
      Double_t cyy = fSigmaYCGFit*fSigmaYCGFit;
      Double_t d   = cyy - cxx;
      Double_t cxy = fCorrXYCGFit * fSigmaXCGFit * fSigmaYCGFit;
      Double_t tandel;
      if (cxy != 0.0)
        tandel = ( d + sqrt(d*d + 4.0*cxy*cxy) ) / (2.0*cxy); 
      else
        tandel = 0.0;

      Double_t sindel = tandel / sqrt(1.0 + tandel*tandel);
      Double_t delta = TMath::ASin(sindel);

      Double_t major =   (cxx + 2.0*tandel*cxy + tandel*tandel*cyy)
	                / (1.0 + tandel*tandel);  

      Double_t minor =   (tandel*tandel*cxx - 2.0*tandel*cxy + cyy)
	                / (1.0 + tandel*tandel);  

      TEllipse efit(fMeanXCGFit, fMeanYCGFit, sqrt(major), sqrt(minor), 
                    0, 360,      delta*kRad2Deg);
      efit.SetLineWidth(3);
      efit.SetLineColor(kMagenta);
      efit.Paint();
    }
}
  
void MStarLocalPos::Print(Option_t *opt) const
{
  TString o = opt;

  if (o.Contains("name", TString::kIgnoreCase) || opt == NULL)
    {
      *fLog << inf << "Star Name: \"" << this->GetName() << "\"" << endl;
    }
      
  if (o.Contains("mag", TString::kIgnoreCase) || opt == NULL)
    {
  
      *fLog << inf << "Star magnitude:" << endl;
      *fLog << inf << " Expected \t" << setw(4) << fMagExp << endl;
      *fLog << inf << " Calcultated \t " << setw(4) << fMagCalc << endl;
      *fLog << inf << " Fitted \t " << setw(4) << fMagFit << endl;
      *fLog << inf << " CGFitted \t " << setw(4) << fMagCGFit << endl;
    }
  
  if (o.Contains("max", TString::kIgnoreCase) || opt == NULL)
    {
      *fLog << inf << "Star Maximum:" << endl;
      *fLog << inf << " Calcultated \t " << setw(4) << fMaxCalc << " uA" 
            << endl;
      *fLog << inf << " Fitted \t " << setw(4) << fMaxFit << " uA" << endl;
      *fLog << inf << " CGFitted \t " << setw(4) << fMaxCGFit << " uA" << endl;
    }
  
  if (o.Contains("pos", TString::kIgnoreCase) || opt == NULL)
    {
      *fLog << inf << "Star position:" << endl;
      *fLog << inf << " Expected \t X " << setw(4) << fXExp 
            << " mm \tY " << setw(4) << fYExp << " mm" << endl;
      *fLog << inf << " Calcultated \t X " << setw(4) << fMeanXCalc 
            << " mm \tY " << setw(4) << fMeanYCalc << " mm" << endl;
      *fLog << inf << " Fitted \t X " << setw(4) << fMeanXFit 
            << " mm \tY " << setw(4) << fMeanYFit << " mm" << endl;
      *fLog << inf << " CGFitted \t X " << setw(4) << fMeanXCGFit 
            << " mm \tY " << setw(4) << fMeanYCGFit << " mm" << endl;
    }

  if (o.Contains("siz", TString::kIgnoreCase) || opt == NULL)
    {
      *fLog << inf << "Star size:" << endl;
      *fLog << inf << " Calcultated \t X " << setw(4) << fSigmaMinorAxisCalc 
            << " mm \tY " << setw(4) << fSigmaMajorAxisCalc << " mm" << endl;
      *fLog << inf << " Fitted \t X " << setw(4) << fSigmaMinorAxisFit 
            << " mm \tY " << setw(4) << fSigmaMajorAxisFit << " mm" << endl;
      *fLog << inf << " CGFitted \t X " << setw(4) << fSigmaXCGFit 
            << " mm \tY " << setw(4) << fSigmaYCGFit << " mm \t correlation" 
            << setw(4) << fCorrXYCGFit << endl;
    }

  if (o.Contains("chi", TString::kIgnoreCase) || opt == NULL)
    {
      *fLog << inf << "Star Fit Quality:" << endl;
      *fLog << inf << " ChiSquare/Ndof \t " << setw(3) << fChiSquare 
            << "/" << fNdof << endl;

      *fLog << inf << "Star CGFit Quality:" << endl;
      *fLog << inf << " ChiSquareCGFit/NdofCGFit \t " << setw(3) 
            << fChiSquareCGFit << "/" << fNdofCGFit << endl;
    }

  if (o.Contains("err", TString::kIgnoreCase) || opt == NULL)
    {
      *fLog << inf << "CGFit Error Matrix of (fMeanXCGFit,fMeanYCGFit) :" 
            << endl;
      *fLog << inf << " xx,xy,yy \t " << setw(3) << fXXErrCGFit << ", " 
            << fXYErrCGFit << ", " << fYYErrCGFit << endl;
    }


}
//--------------------------------------------------------------------------









