#! python
""" Code to convert Stokes parameters to polarization and viceversa
    
Context : SRP
Module  : SRPStokesPol
Author  : Stefano Covino
Date    : 20/08/2018
E-mail  : stefano.covino@brera.inaf.it
URL:    : http://www.merate.mi.astro.it/utenti/covino
Purpose : Convert Stokes parameters to polarization and viceversa

Usage   : SRPStokesPol [-h] [-m] [-n n] [-p P eP Theta eTheta Chi eChi]
                    [-s Q eQ U eU V eV] [-v] [--version]

            -m, --montecarlo      Compute errors by means of a MonteCarlo run
            -n id the number of trials for error computation
            -p P eP Theta eTheta Chi eChi are the normalized polarization parameters
            -s Q eQ U eU V eV  are the normalized Stokes parameters 
    
History : (19/02/2012) First version.
        : (20/03/2013) More digits in output.
        : (21/02/2014) Message syntax correction.
        : (16/07/2014) Polarization bias correction
        : (19/11/2014) Bugs corrected.
        : (20/08/2018) Bias corrected quantitities.
"""

__version__ = '2.2.0'


import argparse, math, sys
import numpy
from SRP.SRPPolarimetry.Pol2Stokes import Pol2Stokes
from SRP.SRPPolarimetry.Stokes2Pol import Stokes2Pol
from SRP.SRPPolarimetry.PolBias import PolBias
from SRP.SRPPolarimetry.PolBiasLims import PolBiasLims
from SRP.SRPStatistics.GenGaussSet import GenGaussSet
from SRP.SRPStatistics.ScoreatPercentile import ScoreatPercentile



parser = argparse.ArgumentParser()
parser.add_argument("-b", "--polbias", action="store_true", help="Correct for polarization bias (Plaszcyinski et al. 2014, MNRAS 439 4048)")
parser.add_argument("-m", "--montecarlo", action="store_true", help="Compute errors by means of a MonteCarlo run")
parser.add_argument("-n", "--ntrial", action="store", type=int, default=1000, help="Number of trials for error computation", metavar='n')
parser.add_argument("-p", "--pol", action="store", type=float, nargs=6, help="Normalized polarization parameters", metavar=('P', 'eP', 'Theta', 'eTheta', 'Chi', 'eChi'))
parser.add_argument("-s", "--stokes", action="store", type=float, nargs=6, help="Normalized Stokes parameters", metavar=('Q', 'eQ', 'U', 'eU', 'V', 'eV'))
parser.add_argument("-v", "--verbose", action="store_true", help="Fully describe operations")
parser.add_argument("--version", action="version", version=__version__)
options = parser.parse_args()


#
if options.montecarlo:
    if options.verbose:
        print("Errors computed by a Monte Carlo run.")
else:
    if options.verbose:
        print("Errors computed by error propagation.")
#
if options.ntrial <= 0 and options.montecarlo:
    parser.error ("Number of trials must be positive.")
#
if (options.pol or options.stokes) and not (options.pol and options.stokes):
    if options.stokes:
        if (options.stokes[0]**2 + options.stokes[2]**2 + options.stokes[4]**2) > 1:
            parser.error("Polarization cannot be larger than 1.")
    elif options.pol:
        if options.pol[0] > 1.0:
            parser.error("Polarization cannot be larger than 1.")
    if options.verbose:
        if options.stokes:
            print("Q, eQ: %.5g +/- %.5g" % (options.stokes[0],options.stokes[1]))
            print("U, eU: %.5g +/- %.5g" % (options.stokes[2],options.stokes[3]))
            print("V, eV: %.5g +/- %.5g" % (options.stokes[4],options.stokes[5]))
        elif options.pol:
            print("P, eP        : %.5g +/- %.5g" % (options.pol[0],options.pol[1]))
            print("Theta, eTheta: %.3g +/- %.3g" % (options.pol[2],options.pol[3]))
            print("Chi, eChi    : %.3g +/- %.3g" % (options.pol[4],options.pol[5]))
    #
    if options.stokes:
        pol = Stokes2Pol(1.0,options.stokes[0],options.stokes[2],options.stokes[4],options.stokes[1],options.stokes[3],options.stokes[5]) 
        if options.montecarlo:
            pols = Stokes2Pol(1.0,GenGaussSet(options.stokes[0],options.stokes[1],options.ntrial),GenGaussSet(options.stokes[2],options.stokes[3],options.ntrial),GenGaussSet(options.stokes[4],options.stokes[5],options.ntrial))
    elif options.pol:
        stokes = Pol2Stokes(1.0,options.pol[0],math.radians(options.pol[2]),math.radians(options.pol[4]),options.pol[1],math.radians(options.pol[3]),math.radians(options.pol[5]))
        if options.montecarlo:
            stokess = Pol2Stokes(1.0,GenGaussSet(options.pol[0],options.pol[1],options.ntrial),GenGaussSet(math.radians(options.pol[2]),math.radians(options.pol[3]),options.ntrial),GenGaussSet(math.radians(options.pol[4]),math.radians(options.pol[5]),options.ntrial))
    #
    if options.stokes:
        P = pol[1]
        T = pol[2]
        C = pol[3]
        if options.montecarlo:
            eP = ScoreatPercentile(pols[1])[3]
            eT = ScoreatPercentile(pols[2])[3]
            eC = ScoreatPercentile(pols[3])[3]            
        else:
            eP = pol[4]
            eT = pol[5]
            eC = pol[6]
    if options.pol:
        Q = stokes[1]
        U = stokes[2]
        V = stokes[3]
        if options.montecarlo:
            eQ = ScoreatPercentile(stokess[1])[3]
            eU = ScoreatPercentile(stokess[2])[3]
            eV = ScoreatPercentile(stokess[3])[3]
        else:
            eQ = stokes[4]
            eU = stokes[5]
            eV = stokes[6]
    #
    if options.polbias and options.stokes:
        nPol = PolBias (P, eP)
        pmin68,pmax68 = PolBiasLims (P/eP,'68')
        pmin95,pmax95 = PolBiasLims (P/eP,'95')
        pmin68 = pmin68*eP
        pmax68 = pmax68*eP
        pmin95 = pmin95*eP
        pmax95 = pmax95*eP
    #
    if options.verbose:
        if options.stokes:
            print("P, eP: %.5g +/- %.5g" % (P,eP))
            print("Theta, eTheta: %.3g +/- %.3g" % (math.degrees(T),math.degrees(eT)))
            print("Chi, eChi    : %.3g +/- %.3g" % (math.degrees(C),math.degrees(eC)))
            if options.polbias:
                print("P/eP: pre %.5g, post: %.5g" % (P/eP,nPol/eP))
                print("Bias corrected P: %.5g" % (nPol))
                print("One sigma limits: %.5g %.5g" % (pmin68,pmax68))
                print("95%% limits: %.5g %.5g" % (pmin95,pmax95))
        elif options.pol:
            print("Q, eQ: %.5g +/- %.5g" % (Q,eQ))
            print("U, eU: %.5g +/- %.5g" % (U,eU))
            print("V, eV: %.5g +/- %.5g" % (V,eV))
    else:
        if options.stokes:
            prstr = "%.5g %.5g %.5g %.5g %.5g %.5g" % (P,eP,math.degrees(T),math.degrees(eT),math.degrees(C),math.degrees(eC))
            if options.polbias:
                prstr = prstr + " %.5g" % (nPol)
                prstr = prstr + "%.5g %.5g" % (pmin68,pmax68)
                prstr = prstr + "%.5g %.5g" % (pmin95,pmax95)
            print(prstr)
        elif options.pol:
            print("%.5g %.5g %.3g %.3g %.3g %.3g" % (Q,eQ,U,eU,V,eV))
else:
    parser.print_help()
#
