Ejemplo n.º 1
0
    def __init__(self, orbit="circular", ld="quad", collCheck=True):
        if not orbit in ["circular", "keplerian"]:
            raise (PE.PyAValError(
                "Invalid option for orbit: " + str(orbit),
                soltuion="Use either 'circular' or 'keplerian'."))
        if not ld in ["quad", "nl"]:
            raise (PE.PyAValError("Invalid option for orbit: " + str(ld),
                                  soltuion="Use either 'quad' or 'nl'."))
        _ZList.__init__(self, orbit, collCheck)

        if (not _importOccultquad) and (ld == "quad"):
            raise (PE.PyARequiredImport(
                "Could not import required shared object library 'occultquad.so'",
                solution=[
                    "Use 'pip install PyAstronomy_ext' to get it.",
                    "Invoke PyA's install script (setup.py) with the --with-ext option.",
                    "Go to 'forTrans' directory of PyAstronomy and invoke\n    f2py -c occultquad.pyf occultquad.f"
                ]))

        if (not _importOccultnl) and (ld == "nl"):
            raise (PE.PyARequiredImport(
                "Could not import required shared object library 'occultquad.so'",
                solution=[
                    "Use 'pip install PyAstronomy_ext' to get it.",
                    "Invoke PyA's install script (setup.py) with the --with-ext option.",
                    "Go to 'forTrans' directory of PyAstronomy and invoke\n    f2py -c occultnl.pyf occultnl.f"
                ]))

        if orbit == "circular":
            plist = ["p", "a", "i", "T0", "per", "b"]
        else:
            # It is an elliptical orbit
            plist = ["p", "a", "i", "per", "b", "e", "Omega", "tau", "w"]

        if ld == "quad":
            plist.extend(["linLimb", "quadLimb"])
        else:
            # Non-linear LD
            plist.extend(["a1", "a2", "a3", "a4"])

        fuf.OneDFit.__init__(self, plist)
        self.freeze(plist)
        self.setRootName("Occultquad")

        if orbit == "keplerian":
            self["w"] = -90.0

        self._orbit = orbit
        self._ld = ld
Ejemplo n.º 2
0
def restoreFromFits(filename, ext=1, verbose=1):
    if not ic.check["pyfits"]:
        raise (PE.PyARequiredImport("pyfits required to use fits file.",
                                    where="Params::updateFitsHeader"))
        return
    import pyfits
    if not os.path.isfile(filename):
        raise (PE.PyAValError("No such file: " + str(filename),
                              where="restoreFromFits",
                              solution="Give correct filename."))
        return
    ff = pyfits.open(filename)[ext]
    try:
        modelname = ff.header['PA_model']
    except:
        raise (PE.pyaOtherErrors("File (" + str(filename) +
                                 ") contains no model.",
                                 where="restoreFromFits",
                                 solution="Use another file."))
        return
    if modelname == 'convLine':
        import convLine as cl
        nLines = ff.header['model_p0']
        model = cl.ConvLine(nLines)
    elif modelname == 'multiGauss1d':
        from PyAstronomy.funcFit import MultiGauss1d
        nLines = ff.header['model_p0']
        model = MultiGauss1d(nLines)
    for p in model.parameters():
        model[p] = ff.header[p]
    return model
Ejemplo n.º 3
0
    def plotDeviance(self, parsList=None):
        """
      Plots value of deviance over parameter values encountered during sampling.

      Parameters
      ----------
      parsList : string or list of strings, optional,
          Refers to a parameter name or a list of parameter names.
          If None, all available parameters are plotted.
    """
        if not ic.check["matplotlib"]:
            PE.warn(PE.PyARequiredImport("To use 'plotHists', matplotlib has to be installed.", \
                                         solution="Install matplotlib."))
            return
        if isinstance(parsList, six.string_types):
            parsList = [parsList]
        tracesDic = {}
        if parsList is not None:
            for parm in parsList:
                self._parmCheck(parm)
                tracesDic[parm] = self[parm]
        else:
            # Use all available traces
            for parm in self.availableParameters():
                tracesDic[parm] = self[parm]

        ps = self.__plotsizeHelper(len(tracesDic))

        for i, [pars, trace] in enumerate(six.iteritems(tracesDic), 1):
            plt.subplot(ps[0], ps[1], i)
            plt.xlabel(pars)
            plt.ylabel("Deviance")
            plt.plot(self[pars], self["deviance"], '.')
Ejemplo n.º 4
0
    def plotHist(self, parsList=None):
        """
      Plots distributions for a number of traces.

      Parameters
      ----------
      parsList : string or list of strings, optional,
          Refers to a parameter name or a list of parameter names.
          If None, all available parameters are plotted.
    """
        if not ic.check["matplotlib"]:
            PE.warn(PE.PyARequiredImport("To use 'plotHists', matplotlib has to be installed.", \
                                         solution="Install matplotlib."))
            return
        if isinstance(parsList, six.string_types):
            parsList = [parsList]
        tracesDic = {}
        if parsList is not None:
            for parm in parsList:
                self._parmCheck(parm)
                tracesDic[parm] = self[parm]
        else:
            # Use all available traces
            for parm in self.availableParameters():
                tracesDic[parm] = self[parm]

        cols, rows = self.__plotsizeHelper(len(tracesDic))

        for i, [pars, trace] in enumerate(tracesDic.items()):
            if len(tracesDic) > 1:
                plt.subplot(rows, cols, i + 1)
            plt.hist(trace, label=pars + " hist")
            plt.legend()
Ejemplo n.º 5
0
def bayesFactors(model1, model2):
    """
    Computes the Bayes factor for two competing models.
    
    The computation is based on Newton & Raftery 1994 (Eq. 13).
    
    Parameters
    ----------
    model1 : PyAstronomy.funcFit.TraceAnalysis instance
        TraceAnalysis for the first model.
    model2 : PyAstronomy.funcFit.TraceAnalysis instance
        TraceAnalysis for the second model.
    
    Returns
    -------
    BF : float
        The Bayes factor BF (neither log10(BF) nor ln(BF)).
        Note that a small value means that the first model
        is favored, i.e., BF=p(M2)/p(M1).
    
  """
    if not ic.check["pymc"]:
        raise(PE.PyARequiredImport("pymc is required to evaluate the bayesFactor", \
                                   solution="Install pymc"))

    logp1 = model1["deviance"] / (-2.)
    logp2 = model2["deviance"] / (-2.)

    # Given a number of numbers x1, x2, ... whose logarithms are given by l_i=ln(x_i) etc.,
    # logsum calculates: ln(sum_i exp(l_i)) = ln(sum_i x_i)
    bf = numpy.exp(
        pymc.flib.logsum(-logp1) - numpy.log(len(logp1)) -
        (pymc.flib.logsum(-logp2) - numpy.log(len(logp2))))
    return bf
Ejemplo n.º 6
0
def planck(T, lam=None, nu=None):
    """
    Evaluate Planck's radiation law.
    
    Depending on whether wavelength or frequency is specified as input, the
    function evaluates:
    
    .. math::
    
        B_{\\nu} = \\frac{2\\pi h \\nu^3}{c^2} \\frac{1}{e^{\\frac{h\\nu}{kT}} - 1}
    
    or
    
    .. math::
    
        B_{\\lambda} = \\frac{2\\pi h c^2}{\\lambda^5} \\frac{1}{e^{\\frac{h c}{\\lambda kT}} - 1} \\; .
    
    If lambda is given (in meters), the output units are W/(m^2 m). To convert into erg/(cm^2 A s),
    the output has to be multiplied by a factor of 1e-7.
    
    Parameters
    ----------
    T : float
        Temperature in Kelvin.
    lam : float or array, optional
        Wavelength in meters.
    nu : float or array, optional
        Frequency in Hz.
    
    Returns
    -------
    Spectral radiance : float or array
        Depending on whether `lam` or `nu` were specified, returns the
        spectral radiance per area and wavelength or frequency. The unit (SI)
        will be W/(m^2 m) if `lam` was given and W/(m^2 Hz) if `nu` was
        specified.
  """
    if _ic.check["quantities"]:
        from PyAstronomy import constants
        c = constants.PyAConstants(unitSystem="SI")
    else:
        raise (PE.PyARequiredImport(
            "You need to install 'quantities' to use this function.\n 'quantities' can be obtained from 'http://pypi.python.org/pypi/quantities'."
        ))
        return None
    if (lam is not None) and (nu is not None):
        raise (PE.PyAParameterConflict(
            "Specify either 'lam' OR 'nu', but not both."))
    if (lam is None) and (nu is None):
        raise (PE.PyAParameterConflict("Specify either 'lam' OR 'nu'."))
    # Parameters have been specified properly
    if lam is not None:
        result = 2. * np.pi * c.h * (c.c**2) / (lam**5)
        result /= (np.exp(c.h * c.c / (lam * c.k * T)) - 1.0)
        return result
    elif nu is not None:
        result = 2. * np.pi * c.h * (nu**3) / (c.c**2)
        result /= (np.exp(c.h * nu / (c.k * T)) - 1.0)
        return result
Ejemplo n.º 7
0
    def plotCorrEnh(self, parsList=None, **plotArgs):
        """
      Produces enhanced correlation plots.
      
      Parameters
      ----------
      parsList : list of string,  optional
          If not given, all available traces are used.
          Otherwise a list of at least two parameters
          has to be specified.
      plotArgs : dict, optional
          Keyword arguments handed to plot procedures of
          pylab. The following keywords are available:
          contour,bins,cmap,origin,interpolation,colors
    """
        if not ic.check["matplotlib"]:
            PE.warn(PE.PyARequiredImport("To use 'plotCorr', matplotlib has to be installed.", \
                                         solution="Install matplotlib."))
            return
        tracesDic = {}
        if parsList is not None:
            for parm in parsList:
                self._parmCheck(parm)
                tracesDic[parm] = self[parm]
            if len(tracesDic) < 2:
                raise(PE.PyAValError("For plotting correlations, at least two valid parameters are needed.", \
                                     where="TraceAnalysis::plotCorr"))
        else:
            # Use all available traces
            for parm in self.availableParameters():
                tracesDic[parm] = self[parm]

        pars = list(tracesDic.keys())
        traces = list(tracesDic.values())

        fontmap = {1: 10, 2: 9, 3: 8, 4: 8, 5: 8}
        if not len(tracesDic) - 1 in fontmap:
            fontmap[len(tracesDic) - 1] = 8

        k = 1
        for j in range(len(tracesDic)):
            for i in range(len(tracesDic)):
                if i > j:
                    plt.subplot(len(tracesDic) - 1, len(tracesDic) - 1, k)
                    #          plt.title("Pearson's R: %1.5f" % self.pearsonr(pars[j],pars[i])[0], fontsize='x-small')
                    plt.xlabel(pars[j], fontsize=fontmap[len(tracesDic) - 1])
                    plt.ylabel(pars[i], fontsize=fontmap[len(tracesDic) - 1])
                    tlabels = plt.gca().get_xticklabels()
                    plt.setp(tlabels, 'fontsize', fontmap[len(tracesDic) - 1])
                    tlabels = plt.gca().get_yticklabels()
                    plt.setp(tlabels, 'fontsize', fontmap[len(tracesDic) - 1])
                    #          plt.plot(traces[j],traces[i],'.',**plotArgs)
                    self.__hist2d(traces[j], traces[i], **plotArgs)
                if i != j:
                    k += 1
Ejemplo n.º 8
0
 def _read_sweetcat(self):
     """
     Read SWEETCat into a pandas DataFrame
     """
     if not _ic.check["pandas"]:
         raise(PE.PyARequiredImport("Could not import pandas module.",
                                    solution="Please install pandas (http://pandas.pydata.org). Please also check the dependencies."))
     else:
         import pandas as pd
     ffn = self._fs.requestFile(self.dataFileName, 'r', gzip.open)
     self.data = pd.read_csv(
         ffn, sep='\t', names=self.names, na_values=['~'])
Ejemplo n.º 9
0
def updateFitsHeader(model, hdr, clobber=False, conf=0.9):
    """
      Update the delivered fits-header with the parameters of the model.

      Parameters:
        - `hdr` - Pyfits header which should be updated with the model parameters.
        - `conf' - Confidence level for MCMC errors.
        - `clobber` - Allows to overwrite parameters which might be already present in the header.
    """
    if not ic.check["pyfits"]:
        raise (PE.PyARequiredImport("pyfits required to use fits file.",
                                    where="Params::updateFitsHeader"))
        return
    try:
        # @FIXME The next line can NEVER work
        #       x=hdr[p]
        raise (PE.pyaOtherErrors(
            " Keyword PA_model already present in fits-header, aborting...",
            where="Params::updateFitsHeader"))
        return
    except:
        pass
    hdr.update('PA_model', model.naming.getRoot(), 'PyAstronomy model type')
    for p in model.parameters():
        if clobber == False:
            try:
                x = hdr[p]
                raise (PE.pyaOtherErrors(" Parameter " + str(p) +
                                         " already present in fits-header",
                                         where="Params::updateFitsHeader"))
                return
            except:
                pass
        hdr.update(p, model[p])
    if ic.check["pymc"]:
        from pymc.utils import hpd
        hdr.update('Conf', conf, "Error Confidence Level")
        for p in model.parameters():
            try:
                v_err = hpd(model.MCMC.trace(p)[:], 1.0 - conf)
                p0, p1 = str(p + '_e0'), str(p + '_e1')
                if len(p0) > 8:
                    raise (PE.pyaOtherErrors(
                        " Cannot save Error for parameter " + str(p) +
                        " because len(" + p0 + ")>8",
                        where="Params::updateFitsHeader"))
                    return
                hdr.update(p0, v_err[0], "Lower confidence boundary")
                hdr.update(p1, v_err[1], "Upper confidence boundary")
            except:
                pass

    return hdr
Ejemplo n.º 10
0
 def _checkPackage(self, p):
     """
   Check whether package is availabel and raise exception otherwise.
   
   Parameters
   ----------
   p : string
       Name of package
 """
     if not ic.check[p]:
         raise(PE.PyARequiredImport("The package '" + str(p) + "' is not currently installed.", \
                                    solution="Please install " + str(p)))
Ejemplo n.º 11
0
def equiTempPlanet(Ts, R, a, albedo=0.0, e=0.0, solarUnits=False):
    """
    Calculate the planetary equilibrium temperature.
    
    The equilibrium temperature is defined, e.g., in
    Laughlin et al. 2011 (ApJ, 729), Eq. 1. Albedo
    was added "by hand".
    
    Note that units have to be consistent for stellar
    radius and large semi-major axis. The `solarUnits`
    flag can be used to use solar units for these
    quantities.
    
    Parameters
    ----------
    Ts : float
        Stellar effective temperature [K].
    R : float
        Radius of the star
    a : float
        Large semi-major axis
    albedo : float
        Albedo of the planetary atmosphere.
        Default is 0.0.
    e : float, optional
        Eccentricity of orbit (default is 0.0).
    solarUnits : boolean, optional
        If this flag is set True, stellar radius and
        semi-major axis are taken to be in solar radii
        and AU.
    
    Returns
    -------
    Equilibrium temperature : float
        The equilibrium temperature of the planet.
  """
    if _ic.check["quantities"]:
        from PyAstronomy import constants as c
    else:
        raise (PE.PyARequiredImport(
            "You need to install 'quantities' to use this function."))
        return None
    if solarUnits:
        a = a * c.AU
        R = R * c.RSun
    if a < R:
        raise (PE.PyAValError(
            "The semi-major axis cannot be smaller than the radius of the star."
        ))
    teq = np.power(1. - albedo, 1./4.) * np.sqrt(R / (2.0 * a)) * Ts \
          / np.power(1.0 - e**2, 1./8.)
    return teq
Ejemplo n.º 12
0
 def getAllDataPandas(self):
     """
   Get all data as pandas DataFrame.
   
   Returns
   -------
   table : DataFrame
       All available data in pandas format.
 """
     if not _ic.check["pandas"]:
         raise(PE.PyARequiredImport("You need to install 'pandas' to use pandas DataFrames.", \
                                    solution="Install 'pandas' package."))
     return self.vot.to_pandas()
Ejemplo n.º 13
0
    def __init__(self):
        _ZList.__init__(self, "circular")
        if not _importOccultnl:
            raise(PE.PyARequiredImport("Could not import required shared object library 'occultquad.so'",\
                                       solution=["Invoke PyA's install script (setup.py) with the --with-ext option.",
                                                 "Go to 'forTrans' directory of PyAstronomy and invoke\n    f2py -c occultnl.pyf occultnl.f"]
                                       ))

        fuf.OneDFit.__init__(
            self, ["p", "a", "i", "a1", "a2", "a3", "a4", "T0", "per", "b"])
        self.freeze(["p", "a", "i", "a1", "a2", "a3", "a4", "T0", "per", "b"])
        self.setRootName("MandelAgolNL")

        self.__zlist = None
Ejemplo n.º 14
0
 def __init__(self):
   _ZList.__init__(self, "circular")
   fuf.OneDFit.__init__(self, ["p", "a", "i", "linLimb", "quadLimb", "T0", "per", "b"])
   self.freeze(["p", "a", "i", "linLimb", "quadLimb", "T0", "per", "b"])
   self.setRootName("PalCirc08")
   
   self._zlist=None
   
   if (not mpmath_imported) and (not boostEll_imported):
     raise(PE.PyARequiredImport("Neither mpmath nor the elliptical integrals from the boost library could be found!", \
                                where="PalLC::__init__", solution="Install mpmath or make Boost library available (more complicated - see documentation)"))
   self.useBoost = False
   if boostEll_imported:
     self.useBoost = True
     self.ell = ell.ell()
Ejemplo n.º 15
0
    def __init__(self, collisionCheck=False):
        _ZList.__init__(self, "keplerian", collisionCheck)
        fuf.OneDFit.__init__(self, [
            "p", "a", "i", "linLimb", "quadLimb", "tau", "per", "b", "w",
            "Omega", "e"
        ])
        self.freeze([
            "p", "a", "i", "linLimb", "quadLimb", "tau", "per", "b", "w",
            "Omega", "e"
        ])
        self.setRootName("Pal08")
        self["per"] = 1.0
        self["w"] = -90

        self._zlist = None

        if (not mpmath_imported) and (not boostEll_imported):
            raise (PE.PyARequiredImport(
                "Neither mpmath nor the elliptical integrals from the boost library could be found!",
                where="PalLC::__init__",
                solution=
                "Install mpmath or make Boost library available (more complicated - see documentation)"
            ))
        self.useBoost = False
        if boostEll_imported:
            self.useBoost = True
            self.ell = ell.ell()

        self.collisionCheck = collisionCheck

        # Wrap get/setitem to inform about change in parameter name
        T0paE = PE.PyADeprecationError(
            "The parameter 'T0pa' in PalLCKep had to be renamed 'tau'.",
            solution="Use 'tau' instead of 'T0pa'.")

        def getitem(specifier, **kwargs):
            if specifier == "T0pa":
                PE.warn(T0paE)
            return PalLC.__getitem__(self, specifier, **kwargs)

        self.__getitem__ = getitem

        def setitem(specifier, value):
            if specifier == "T0pa":
                PE.warn(T0paE)
            PalLC.__setitem__(self, specifier, value)

        self.__setitem__ = setitem
Ejemplo n.º 16
0
    def plot(self, *args, **kwargs):
        """
      Creates a matplotlib figure and axes class instance to visualize the result.
      
      Parameters:
        - `FAPlevels` - optional, List of false-alarm probability (FAP) levels
        - `*args` - optional, Arguments passed to plot method of axes class.
        - `**kwargs` - optional, Keyword arguments passed plot method to axes class.
      
      This method provides a quick and simple way to visualize the results of the a
      periodogram calculation.
      
      Returns:
        The created *Figure* and *Axes* class instances.
    """
        if not _mplImport:
            raise(PE.PyARequiredImport("To use this function matplotlib must be installed.", \
                                       where="PeriodBase::plot", solution=["Install matplotlib.", "Avoid call and use custom plotting interface."]))
        fig = mpl.figure()
        ax = fig.add_subplot(1, 1, 1)

        if "FAPlevels" in kwargs:
            fapLvs = numpy.array(kwargs["FAPlevels"])
            del kwargs["FAPlevels"]
            powLvs = self.powerLevel(fapLvs)
            for i, powLv in enumerate(powLvs):
                ax.plot([self.freq.min(), self.freq.max()], [powLv, powLv],
                        'k--')
                ax.annotate("FAP " + ("%2.3g" % fapLvs[i]),
                            xy=(self.freq.max(), powLv),
                            xytext=None,
                            xycoords='data',
                            textcoords='data',
                            arrowprops=None,
                            horizontalalignment="right")

        if self.label is None:
            ax.set_title("Periodogram")
            ax.set_xlabel("Frequency")
            ax.set_ylabel("Power")
        else:
            ax.set_title(self.label["title"])
            ax.set_xlabel(self.label["xlabel"])
            ax.set_ylabel(self.label["ylabel"])
        ax.plot(self.freq, self.power, *args, **kwargs)

        return fig, ax
Ejemplo n.º 17
0
    def __init__(self, skipUpdate=False, forceUpdate=False):

        if not _ic.check["astropy"]:
            raise(PE.PyARequiredImport("The 'astropy' package is not installed. astropy is required to read VO tables.",
                                       solution="Please install 'astropy'."))

        configFilename = os.path.join("pyasl", "resBased", "epeuvo.cfg")
        pp.PyAUpdateCycle.__init__(self, configFilename, "ExoUpdate")
        self.dataFileName = os.path.join("pyasl", "resBased", "epeu.vo.gz")
        self._fs = pp.PyAFS()
        if forceUpdate:
            self._update(self._download)
        elif (self.needsUpdate() or (not self._fs.fileExists(self.dataFileName))) and (not skipUpdate):
            # Download data if data file does not exist or
            # regular update is indicated
            self._update(self._download)
        self._readData()
Ejemplo n.º 18
0
    def plotTraceHist(self, parm):
        """
      Plots trace and histogram (distribution).

      Parameters
      ----------
      parm : string
          The variable name.
    """
        if not ic.check["matplotlib"]:
            PE.warn(PE.PyARequiredImport("To use 'plotTraceHist', matplotlib has to be installed.", \
                                         solution="Install matplotlib."))
            return
        self._parmCheck(parm)

        plt.subplot(1, 2, 1)
        self.plotTrace(parm)
        plt.subplot(1, 2, 2)
        self.plotHist(parm)
Ejemplo n.º 19
0
 def plotTrace(self, parm, fmt='b-'):
     """
   Plots the trace.
   
   Parameters
   ----------
   parm : string
       The variable name.
   fmt : string, optional
       The matplotlib format string used to plot the trace.
       Default is 'b-'.
 """
     if not ic.check["matplotlib"]:
         PE.warn(PE.PyARequiredImport("To use 'plotTrace', matplotlib has to be installed.", \
                                      solution="Install matplotlib."))
         return
     self._parmCheck(parm)
     plt.plot(self[parm], fmt, label=parm + " trace")
     plt.legend()
Ejemplo n.º 20
0
def plotFIP():
  """
    Show a plot of first ionization energy vs. atomic number. 
  """
  if not _ic.check["matplotlib"]:
    raise(PE.PyARequiredImport("Could not import matplotlib."))
  
  fip = FirstIonizationPot()
  z = range(1,31,1)
  fips = []
  for an in z:
    fips.append(fip.getFIP(an)[0])
  
  import matplotlib.pylab as plt
  plt.xlabel("Atomic number")
  plt.ylabel("First ionization energy [eV]")
  plt.plot(z, fips, 'bp-')
  plt.show()
  
  
  
Ejemplo n.º 21
0
    def _plot(self):
        """
      Create a plot.
    """
        try:
            import matplotlib.pylab as plt
        except ImportError:
            raise (PE.PyARequiredImport("Could not import matplotlib.pylab."))
        self.fig = plt.figure()
        self.fig.subplots_adjust(hspace=0.35)
        self.ax = self.fig.add_subplot(2, 1, 1)
        self.ax.set_title("Normalized periodogram")
        self.ax.set_xlabel("Frequency")
        self.ax.set_ylabel("Power")
        self.ax.plot(self.freq, self.power, 'b.--')

        self.ax = self.fig.add_subplot(2, 1, 2)
        self.ax.set_title("Data")
        self.ax.set_xlabel("Time")
        self.ax.set_ylabel("Data")
        self.ax.plot(self.t, self.y, 'r.--')

        plt.show()
Ejemplo n.º 22
0
 def __init__(self, lineList, uniSig=None, modelBinsize=0.005, useFastRB=True, verbose=False, onlyAbs=True):
   
   if not ic.check["scipy"]:
     raise(PE.PyARequiredImport("Could not import scipy.", \
                                solution="Install scipy."))
   # Check whether depths are given
   self._depthsGiven = (len(lineList[0,::]) == 3)
   if (not self._depthsGiven) and (uniSig is None):
     raise(PE.PyAValError("No width and no depth given.", \
                          solution="Specify line depth in `lineList` or use `uniSig`."))
   # Check whether unified sigma shall be used
   # Note: Line depth will be ignored then
   self._uniSig = uniSig 
   
   # Only absorption lines
   self._onlyAbs = onlyAbs
   # Verbosity
   self._verbose = verbose
   # Use fast rotational broadening?
   self._usefastRB = useFastRB
   # Save binsize for the model
   self._modelBinsize = modelBinsize
   # Copy line list
   self._lineList = lineList.copy()
   # Number of lines
   self._nl = len(lineList[::,0])
   # A MultiGaussFit object
   self._mg = fuf.MultiGauss1d(self._nl)
   # Store all parameter names from GaussFit
   pars = list(self._mg.parameters().keys())
   # Remove lin and off from multiGauss keys
   pars.remove("lin")
   pars.remove("off")
   
   pars.extend(["lineScale", "scale", "eps", "vrad", "vsini"])
   fuf.OneDFit.__init__(self, pars)
   # Name the model
   self.setRootName("LineListGauss")
   
   # Assign start values
   for i in range(self._nl):
     p = str(i+1)
     # Assign position
     self._mg["mu"+p] = lineList[i,0]
     self["mu"+p] = lineList[i,0]
     # Assign amplitude/EW
     # Note: Positive EWs correspond to absorption lines
     self._mg["A"+p] = -lineList[i,1]
     self["A"+p] = lineList[i,1]
     # Assign width (sigma)
     if self._depthsGiven and (self._uniSig is None):
       # Depth IS given and no unified sigma specified
       self._mg["sig"+p] = abs(lineList[i,1])/((1.-lineList[i,2]) * np.sqrt(2.*np.pi))
       self["sig"+p] = self._mg["sig"+p] 
     elif not (self._uniSig is None):
       # uniSig IS given
       self._mg["sig"+p] = self._uniSig
       self["sig"+p] = self._mg["sig"+p] 
   
   self["scale"] = 1.0
   self["lineScale"] = 1.0
   
   if self._onlyAbs:
     # Apply restrictions to prevent emission lines
     for i in range(self._nl):
       p = str(i+1)
       self.setRestriction({"A"+p:[0.0, None]})
Ejemplo n.º 23
0
def ibtrapz(x, y, x0, x1, iaout=False):
    """
    Use the trapezoid rule to integrate and interpolate boundary values.
    
    Can be used for integration on tabled data, where the integration boundaries
    are not located on the grid. The values to use at the boundaries are
    determined using linear interpolation.
    
    Parameters
    ----------
    x,y : arrays
        The data.
    x0, x1 : float
        The integration boundaries.
    iaout : boolean, optional
        If True, the arrays used internally for
        integration are also returned. The default
        is False.
    
    Returns
    -------
    Integral : float
        The value of the resulting integral.
    xi, yi : arrays, optional
        Internally used arrays for integration including
        the values derived at the boundaries. Only returned
        if `iaout` is set to True.
  """
    if not _ic.check["scipy"]:
        raise(PE.PyARequiredImport("scipy could not be imported.", \
                                   where="ibtrapz", \
                                   solution="Please install scipy to use ibtrapz."))
    import scipy.interpolate as sci
    import scipy.integrate as scinteg
    if (x1 < x0):
        raise(PE.PyAValError("x1 must be larger than x0.", \
                             where="ibtrapz", \
                             solution="Exchange boundaries."))
    if np.any(x[1:] - x[0:-1] < 0.0):
        raise(PE.PyAValError("x axis must be in ascending order.", \
                             where="ibtrapz", \
                             solution="Sort values."))
    if (x0 < np.min(x)) or (x1 > np.max(x)):
        raise(PE.PyAValError("One or both integration boundaries are beyond the range of data given.", \
                             where="ibtrapz", \
                             solution="Give more data or adjust integration boundaries."))
    # Interpolate at integration boundaries
    fi = sci.interp1d(x, y)
    y0, y1 = fi(x0), fi(x1)
    # Search data within boundaries
    indi = np.where((x > x0) & (x < x1))[0]
    # Construct arrays to be used in integration
    xi = np.zeros(len(indi) + 2)
    yi = np.zeros(len(indi) + 2)
    xi[1:-1] = x[indi]
    yi[1:-1] = y[indi]
    xi[0] = x0
    xi[-1] = x1
    yi[0] = y0
    yi[-1] = y1

    if iaout:
        return scinteg.trapz(yi, xi), xi, yi
    return scinteg.trapz(yi, xi)
Ejemplo n.º 24
0
def crosscorrRV(w,
                f,
                tw,
                tf,
                rvmin,
                rvmax,
                drv,
                mode="doppler",
                skipedge=0,
                edgeTapering=None):
    """
    Cross-correlate a spectrum with a template.
    
    The algorithm implemented here works as follows: For
    each RV shift to be considered, the wavelength axis
    of the template is shifted, either linearly or using
    a proper Doppler shift depending on the `mode`. The
    shifted template is then linearly interpolated at
    the wavelength points of the observation
    (spectrum) to calculate the cross-correlation function.
    
    Parameters
    ----------
    w : array
        The wavelength axis of the observation.
    f : array
        The flux axis of the observation.
    tw : array
        The wavelength axis of the template.
    tf : array
        The flux axis of the template.
    rvmin : float
        Minimum radial velocity for which to calculate
        the cross-correlation function [km/s].
    rvmax : float
        Maximum radial velocity for which to calculate
        the cross-correlation function [km/s].
    drv : float
        The width of the radial-velocity steps to be applied
        in the calculation of the cross-correlation
        function [km/s].
    mode : string, {lin, doppler}, optional
        The mode determines how the wavelength axis will be
        modified to represent a RV shift. If "lin" is specified,
        a mean wavelength shift will be calculated based on the
        mean wavelength of the observation. The wavelength axis
        will then be shifted by that amount. If "doppler" is
        specified (the default), the wavelength axis will
        properly be Doppler-shifted.
    skipedge : int, optional
        If larger zero, the specified number of bins will be
        skipped from the begin and end of the observation. This
        may be useful if the template does not provide sufficient
        coverage of the observation.
    edgeTapering : float or tuple of two floats
        If not None, the method will "taper off" the edges of the
        observed spectrum by multiplying with a sine function. If a float number
        is specified, this will define the width (in wavelength units)
        to be used for tapering on both sides. If different tapering
        widths shall be used, a tuple with two (positive) numbers
        must be given, specifying the width to be used on the low- and
        high wavelength end. If a nonzero 'skipedge' is given, it
        will be applied first. Edge tapering can help to avoid
        edge effects (see, e.g., Gullberg and Lindegren 2002, A&A 390).
    
    Returns
    -------
    dRV : array
        The RV axis of the cross-correlation function. The radial
        velocity refer to a shift of the template, i.e., positive
        values indicate that the template has been red-shifted and
        negative numbers indicate a blue-shift of the template.
        The numbers are given in km/s.
    CC : array
        The cross-correlation function.
  """
    if not _ic.check["scipy"]:
        raise(PE.PyARequiredImport("This routine needs scipy (.interpolate.interp1d).", \
                                   where="crosscorrRV", \
                                   solution="Install scipy"))
    import scipy.interpolate as sci
    # Copy and cut wavelength and flux arrays
    w, f = w.copy(), f.copy()
    if skipedge > 0:
        w, f = w[skipedge:-skipedge], f[skipedge:-skipedge]

    if edgeTapering is not None:
        # Smooth the edges using a sine
        if isinstance(edgeTapering, float):
            edgeTapering = [edgeTapering, edgeTapering]
        if len(edgeTapering) != 2:
            raise(PE.PyAValError("'edgeTapering' must be a float or a list of two floats.", \
                                 where="crosscorrRV"))
        if edgeTapering[0] < 0.0 or edgeTapering[1] < 0.0:
            raise(PE.PyAValError("'edgeTapering' must be (a) number(s) >= 0.0.", \
                                 where="crosscorrRV"))
        # Carry out edge tapering (left edge)
        indi = np.where(w < w[0] + edgeTapering[0])[0]
        f[indi] *= np.sin((w[indi] - w[0]) / edgeTapering[0] * np.pi / 2.0)
        # Carry out edge tapering (right edge)
        indi = np.where(w > (w[-1] - edgeTapering[1]))[0]
        f[indi] *= np.sin((w[indi] - w[indi[0]]) / edgeTapering[1] * np.pi /
                          2.0 + np.pi / 2.0)

    # Speed of light in km/s
    c = 299792.458
    # Check order of rvmin and rvmax
    if rvmax <= rvmin:
        raise(PE.PyAValError("rvmin needs to be smaller than rvmax.",
                             where="crosscorrRV", \
                             solution="Change the order of the parameters."))
    # Check whether template is large enough
    if mode == "lin":
        meanWl = np.mean(w)
        dwlmax = meanWl * (rvmax / c)
        dwlmin = meanWl * (rvmin / c)
        if (tw[0] + dwlmax) > w[0]:
            raise(PE.PyAValError("The minimum wavelength is not covered by the template for all indicated RV shifts.", \
                                 where="crosscorrRV", \
                                 solution=["Provide a larger template", "Try to use skipedge"]))
        if (tw[-1] + dwlmin) < w[-1]:
            raise(PE.PyAValError("he maximum wavelength is not covered by the template for all indicated RV shifts.", \
                                 where="crosscorrRV", \
                                 solution=["Provide a larger template", "Try to use skipedge"]))
    elif mode == "doppler":
        # Ensure that the template covers the entire observaion for all shifts
        maxwl = tw[-1] * (1.0 + rvmin / c)
        minwl = tw[0] * (1.0 + rvmax / c)
        if minwl > w[0]:
            raise(PE.PyAValError("he minimum wavelength is not covered by the template for all indicated RV shifts.", \
                                 where="crosscorrRV", \
                                 solution=["Provide a larger template", "Try to use skipedge"]))
        if maxwl < w[-1]:
            raise(PE.PyAValError("The maximum wavelength is not covered by the template for all indicated RV shifts.", \
                                 where="crosscorrRV", \
                                 solution=["Provide a larger template", "Try to use skipedge"]))
    else:
        raise(PE.PyAValError("Unknown mode: " + str(mode), \
                             where="crosscorrRV", \
                             solution="See documentation for available modes."))
    # Calculate the cross correlation
    drvs = np.arange(rvmin, rvmax, drv)
    cc = np.zeros(len(drvs))
    for i, rv in enumerate(drvs):
        if mode == "lin":
            # Shift the template linearly
            fi = sci.interp1d(tw + meanWl * (rv / c), tf)
        elif mode == "doppler":
            # Apply the Doppler shift
            fi = sci.interp1d(tw * (1.0 + rv / c), tf)
        # Shifted template evaluated at location of spectrum
        cc[i] = np.sum(f * fi(w))
    return drvs, cc
Ejemplo n.º 25
0
def read1dFitsSpec(fn, hdu=0, fullout=False, CRPIX1=None, keymap={}):
    """
    Read a simple 1d spectrum from fits file.

    Reads a 1d-spectrum from a file and constructs the
    associated wavelength axis. To this end, the expression:
    wvl = ((np.arange(N) + 1.0) - CRPIX1) * CDELT1 + CRVAL1
    will be evaluated, where N is the number of bins and
    CRPIX1, CDELT1, and CRVAL1 are header keywords.

    Parameters
    ----------
    fn : string
        Filename
    hdu : int, optional
        The number of the HDU to be used. The default
        is 0, i.e., the primary HDU.
    fullout : boolean, optional
        If True, the header keywords used to construct
        the wavelength axis will be returned. The default
        is False.
    CRPIX1 : int, optional
        Can be used to circumvent missing CRPIX1 entry.
    keymap : dict, optional
        Can be used to map header keywords

    Returns
    -------
    wvl : array
        The wavelength array.
    flx : array
        The flux array.

    Examples
    --------

    ::

      from PyAstronomy import pyasl
      wvl, flx = pyasl.read1dFitsSpec("mySpectrum.fits")
    """
    if (not _ic.check["pyfits"]) and (not _ic.check["astropy.io.fits"]):
        raise(PE.PyARequiredImport("Could neither import module 'pyfits' and 'astropy.io.fits'.",
                                   where="read1dFitsSpec",
                                   solution="Install pyfits: http://www.stsci.edu/institute/software_hardware/pyfits"))

    if not os.path.isfile(fn):
        raise(PE.PyAFileError(fn, "ne",
                              where="read1dFitsSpec",
                              solution="Check file name."))

    if _ic.check["pyfits"]:
        import pyfits
    else:
        import astropy.io.fits as pyfits

    hl = pyfits.open(fn)

    naxis = hl[hdu].header["NAXIS"]
    if hl[hdu].header["NAXIS"] != 1:
        if hl[hdu].header["NAXIS"] == 2 and hl[hdu].header["NAXIS2"] == 1:
            pass
        else:
            raise(PE.PyAValError("There is more than one axis (NAXIS = " + str(naxis) + ", actual value is " + str(hl[hdu].header["NAXIS"]) + ").",
                                 where="read1dFitsSpec",
                                 solution="Check file and HDU."))

    hkeys = {"CRVAL1": None, "CRPIX1": CRPIX1, "CDELT1": None}
    for k in hkeys.keys():
        if k not in keymap:
            keymap[k] = k

    for k in hkeys.keys():
        if hkeys[k] is not None:
            continue
        if not keymap[k] in hl[hdu].header:
            raise(PE.PyAValError("Header does not contain required keyword '" + str(keymap[k]) + "'",
                                 where="read1dFitsSpec",
                                 solution="Check file and HDU."))
        hkeys[k] = hl[hdu].header[keymap[k]]

    N = int(hl[hdu].header["NAXIS1"])

    # Construct wvl axis
    wvl = ((np.arange(N) + 1.0) - hkeys["CRPIX1"]
           ) * hkeys["CDELT1"] + hkeys["CRVAL1"]
    # Get flux
    if naxis == 1:
        flx = np.array(hl[hdu].data)
    elif naxis == 2:
        flx = np.array(hl[hdu].data[0])

    if fullout:
        # Full output
        return wvl, flx, hkeys

    return wvl, flx
Ejemplo n.º 26
0
def write1dFitsSpec(fn,
                    flux,
                    wvl=None,
                    waveParams=None,
                    fluxErr=None,
                    header=None,
                    clobber=False,
                    refFileName=None,
                    refFileExt=0):
    """
    Write a 1d spectrum with equidistant binning to a fits file.

    Write a 1d-spectrum to a file. Wavelength axis and header keywords
    are related through the following expression:
    wvl = ((np.arange(N) + 1.0) - CRPIX1) * CDELT1 + CRVAL1,
    where CRPIX1, CDELT1, and CRVAL1 are the
    relevant header keywords.

    The function allows to specify an existing fits extension, from
    which the header will be cloned. Alternatively, an arbitrary,
    user-defined header may be given.

    Parameters
    ----------
    fn : string
        Filename
    flux : array
        Flux array
    wvl : array, optional
        Wavelength array. Either the wavelength array or the header
        keywords have to be provided (see `waveParams`). 
    waveParams : dict, optional
        Wavelength information required in the fits-header.
        Required keys are CDELT, CRVAL, CRPIX or (CDELT1, CRVAL1, CRPIX1).
    fluxErr : array, optional
        Flux errors. If given, the error will be stored in an additional extension.
    header : dict, optional
        Dictionary with header information to be transfered to the new file.
        Note that the wavelength information will be overwritten
        by the information given to this routine.
        If both, a reference file to clone the header from and the header parameters
        are given, the cloned header from the reference file will be overwritten and
        extended by the keywords specified here.
    refFileName : string, optional
        Clone header keywords from a reference file.
        Note that the wavelength information will be overwritten by the information
        by the information given to this routine.
    refFileExt : int, optional
        Reference-file extension to be used for cloning the header keywords.
        The default is 0.

    """

    reservedKeyWords = [
        "BITPIX", "SIMPLE", "NAXIS", "NAXIS1", "CDELT1", "CRPIX1", "CRVAL1",
        "EXTEND"
    ]

    if (not _ic.check["pyfits"]) and (not _ic.check["astropy.io.fits"]):
        raise (PE.PyARequiredImport(
            "Could neither import module 'pyfits' and 'astropy.io.fits'.",
            where="write1dFitsSpec",
            solution=
            "Install pyfits: http://www.stsci.edu/institute/software_hardware/pyfits"
        ))

    if wvl is None and waveParams is None:
        raise (PE.PyAValError(
            "The wavelength axis is not defined, i.e., neither \'wvl\' nor \'waveParams\' is specified.",
            where="write1dFitsSpec",
            solution=
            "Provide wavelength array as \'wvl\' or wavelength information as \'waveParams\'."
        ))

    if wvl is not None and waveParams is not None:
        raise (PE.PyAValError(
            "You provided the wavelength axis as \'wvl\' AND wavelength information as \'waveParams\'. Don't know which to use.",
            where="write1dFitsSpec",
            solution=
            "Provide only wavelength array via \'wvl\' or wavelength information via \'waveParams\'."
        ))

    if wvl is not None:
        # Check whether the wavelength axis is equidistant
        dwl = wvl[1:] - wvl[0:-1]
        if (np.max(dwl) - np.min(dwl)) / np.max(dwl) > 1e-6:
            raise (PE.PyAValError(
                "Wavelength axis seems not to be equidistant.",
                where="write1dFitsSpec",
                solution=[
                    "Check wavelength array.",
                    "Consider passing wavelength information via `waveParams`."
                ]))

    if os.path.isfile(fn) and not clobber:
        raise (PE.PyAFileError(
            fn,
            "ae",
            where="write1dFitsSpec",
            solution="File exists; set clobber=True to overwrite."))

    if _ic.check["pyfits"]:
        import pyfits
    else:
        import astropy.io.fits as pyfits

    # Put the flux into the output file.
    # Generate primary HDU
    hdu = pyfits.PrimaryHDU(flux)

    if refFileName:
        # If the is a reference file, its header will be used to populate
        # the header of the file to be written.
        if not os.path.isfile(refFileName):
            raise (PE.PyAFileError(str(refFileName),
                                   "ne",
                                   where="write1dFitsSpec",
                                   solution="Check file name."))
        ff = pyfits.open(refFileName)[refFileExt]

        for k in ff.header.keys():
            if k not in reservedKeyWords and k != "COMMENT":
                try:
                    if len(k) > 8:
                        hdu.header["HIERARCH " + k] = ff.header[k]
                    else:
                        hdu.header[k] = ff.header[k]
                except:
                    PE.warn(
                        PE.PyAValError("Cannot write keyword <" + str(k) +
                                       "> with content " + str(ff.header[k])))

    if header is not None:
        # A use-defined header was specified
        for k in header.keys():
            hdu.header[k] = header[k]

    # Header keywords relevant for wavelength axis
    hk = {}
    # The only allowed type here
    hk["CTYPE1"] = "Linear"
    # If wavelength array is provided, create header keywords:
    if wvl is not None:
        hk["CRPIX1"] = 1
        hk["CRVAL1"] = wvl[0]
        hk["CDELT1"] = float(wvl[-1] - wvl[0]) / (len(wvl) - 1)
    elif waveParams is not None:
        requiredKeys = ["CRPIX", "CRVAL", "CDELT"]
        # Counts whether all required keywords are provided
        count = 0
        for k in requiredKeys:
            subCount = 0
            for p in six.iterkeys(waveParams):
                if p.upper() == k or p.upper() == k + "1":
                    hk[k + "1"] = waveParams[p]
                    subCount += 1
            if subCount == 1:
                count += 1
            else:
                # This occurs if, e.g., both "CRVAL" and "CRVAL1" are present
                raise (PE.PyAValError(
                    "The wavelength parameters provided via \'waveParams\' contain ambiguous parameters. "
                    + "You provided multiple values for " + k + ".",
                    where="write1dFitsSpec",
                    solution=
                    "Check content of \'waveParams\' so that only one value for "
                    + k +
                    " is provided (including lower/upper case and presence of a trailing \'1\'."
                ))
        if count < 3:
            raise (PE.PyAValError(
                "You provided an incomplete set of waveParams.",
                where="write1dFitsSpec",
                solution="Required keywords are CRPIX, CRVAL, and CDELT."))

    # (Over-)Write wavelength-related header information
    for k in hk.keys():
        hdu.header[k] = hk[k]

    if not fluxErr is None:
        # An error on the flux was given
        hdue = pyfits.ImageHDU(fluxErr)
        for k in hk.keys():
            # Add wavelength information to error header
            hdue.header[k] = hk[k]
        hdulist = pyfits.HDUList([hdu, hdue])
    else:
        hdulist = pyfits.HDUList([hdu])

    hdulist.writeto(fn, overwrite=clobber)
Ejemplo n.º 27
0
def sunpos2(jd,
            end_jd=None,
            jd_steps=None,
            outfile=None,
            radian=False,
            plot=False,
            full_output=False):
    """
    Compute right ascension and declination of the Sun at a given time.
    
    Parameters
    ----------
    jd : float
         The Julian date
    end_jd : float, optional
         The end of the time period as Julian date. If given,
         `sunpos` computes RA and DEC at `jd_steps` time points
         between `jd` and ending at `end_jd`.
    jd_steps : integer, optional
         The number of steps between `jd` and `end_jd`
         for which RA and DEC are to be calculated.
    outfile : string, optional
         If given, the output will be written to a file named according
         to `outfile`.
    radian : boolean, optional
         Results are returned in radian instead of in degrees.
         Default is False.
    plot : boolean, optional
         If True, the result is plotted.
    full_output: boolean, optional
         If True, `sunpos`, additionally, returns the elongation and
         obliquity of the Sun.

    Returns
    -------
    Time : array
        The JDs for which calculations where carried out.
    Ra : array
        Right ascension of the Sun.
    Dec : array
        Declination of the Sun.
    Elongation : array, optional
        Elongation of the Sun (only of `full_output`
        is set to True).
    Obliquity : array, optional
        Obliquity of the Sun (only of `full_output`
        is set to True).

    Notes
    -----
    
    .. note:: This function was ported from the IDL Astronomy User's Library.

    :IDL - Documentation:

    NAME:
          SUNPOS
    PURPOSE:
          To compute the RA and Dec of the Sun at a given date.
    
    CALLING SEQUENCE:
          SUNPOS, jd, ra, dec, [elong, obliquity, /RADIAN ]
    INPUTS:
          jd    - The Julian date of the day (and time), scalar or vector
                  usually double precision
    OUTPUTS:
          ra    - The right ascension of the sun at that date in DEGREES
                  double precision, same number of elements as jd
          dec   - The declination of the sun at that date in DEGREES
    
    OPTIONAL OUTPUTS:
          elong - Ecliptic longitude of the sun at that date in DEGREES.
          obliquity - the obliquity of the ecliptic, in DEGREES
    
    OPTIONAL INPUT KEYWORD:
          /RADIAN - If this keyword is set and non-zero, then all output variables 
                  are given in Radians rather than Degrees
    
    NOTES:
          Patrick Wallace (Rutherford Appleton Laboratory, UK) has tested the
          accuracy of a C adaptation of the sunpos.pro code and found the 
          following results.   From 1900-2100 SUNPOS  gave 7.3 arcsec maximum 
          error, 2.6 arcsec RMS.  Over the shorter interval 1950-2050 the figures
          were 6.4 arcsec max, 2.2 arcsec RMS.  
    
          The returned RA and Dec are in the given date's equinox.
    
          Procedure was extensively revised in May 1996, and the new calling
          sequence is incompatible with the old one.
    METHOD:
          Uses a truncated version of Newcomb's Sun.    Adapted from the IDL
          routine SUN_POS by CD Pike, which was adapted from a FORTRAN routine
          by B. Emerson (RGO).
    EXAMPLE:
          (1) Find the apparent RA and Dec of the Sun on May 1, 1982
          
          IDL> jdcnv, 1982, 5, 1,0 ,jd      ;Find Julian date jd = 2445090.5   
          IDL> sunpos, jd, ra, dec
          IDL> print,adstring(ra,dec,2)
                   02 31 32.61  +14 54 34.9
    
          The Astronomical Almanac gives 02 31 32.58 +14 54 34.9 so the error
                  in SUNPOS for this case is < 0.5".      
    
          (2) Find the apparent RA and Dec of the Sun for every day in 1997
    
          IDL> jdcnv, 1997,1,1,0, jd                ;Julian date on Jan 1, 1997
          IDL> sunpos, jd+ dindgen(365), ra, dec    ;RA and Dec for each day 
    
    MODIFICATION HISTORY:
          Written by Michael R. Greason, STX, 28 October 1988.
          Accept vector arguments, W. Landsman     April,1989
          Eliminated negative right ascensions.  MRG, Hughes STX, 6 May 1992.
          Rewritten using the 1993 Almanac.  Keywords added.  MRG, HSTX, 
                  10 February 1994.
          Major rewrite, improved accuracy, always return values in degrees
          W. Landsman  May, 1996 
          Added /RADIAN keyword,    W. Landsman       August, 1997
          Converted to IDL V5.0   W. Landsman   September 1997
  """

    if end_jd is None:
        # Form time in Julian centuries from 1900.0
        start_jd = (jd - 2415020.0) / 36525.0
        # Zime array
        time = np.array(start_jd)
    else:
        if jd >= end_jd:
            raise(PE.PyAValError("`end_jd` needs to be larger than `jd`.", \
                  where="sunpos", \
                  solution="Modify the parameters."))
            if jd_steps is None:
                raise(PE.PyAValError("You specified `end_jd`, but no value for `jd_steps`.", \
                      where="sunpos", \
                      solution="Specify `jd_steps`, e.g., given jd_steps=10"))
        # Form time in Julian centuries from 1900.0
        start_jd = (jd - 2415020.0) / 36525.0
        end_jd = (end_jd - 2415020.0) / 36525.0
        # Time array
        timestep = (end_jd - start_jd) / float(jd_steps)
        time = np.arange(start_jd, end_jd, timestep)

    # Mean solar longitude
    sunlon = (279.696678 + idlMod((36000.768925 * time), 360.0)) * 3600.0

    # Allow for ellipticity of the orbit (equation of center)
    # using the Earth's mean anomaly ME
    me = 358.475844 + idlMod((35999.049750 * time), 360.0)
    ellcor = (6910.1 - 17.2 * time) * np.sin(
        me * np.pi / 180.) + 72.3 * np.sin(2.0 * me * np.pi / 180.)
    sunlon += ellcor

    # Allow for the Venus perturbations using the mean anomaly of Venus MV
    mv = 212.603219 + idlMod((58517.803875 * time), 360.0)
    vencorr = 4.8 * np.cos( (299.1017 + mv - me)*np.pi/180. ) + \
              5.5 * np.cos( (148.3133 +  2.0 * mv  -  2.0 * me )*np.pi/180. ) + \
              2.5 * np.cos( (315.9433 +  2.0 * mv  -  3.0 * me )*np.pi/180. ) + \
              1.6 * np.cos( (345.2533 +  3.0 * mv  -  4.0 * me )*np.pi/180. ) + \
              1.0 * np.cos( (318.15   +  3.0 * mv  -  5.0 * me )*np.pi/180. )
    sunlon += vencorr

    # Allow for the Mars perturbations using the mean anomaly of Mars MM
    mm = 319.529425 + idlMod((19139.858500 * time), 360.0)
    marscorr = 2.0 * np.cos( (343.8883 -  2.0 * mm  +  2.0 * me)*np.pi/180. ) + \
              1.8 * np.cos( (200.4017 -  2.0 * mm  + me)*np.pi/180. )
    sunlon += marscorr

    # Allow for the Jupiter perturbations using the mean anomaly of Jupiter MJ
    mj = 225.328328 + idlMod((3034.6920239 * time), 360.0)
    jupcorr = 7.2 * np.cos( (179.5317 - mj + me )*np.pi/180. ) + \
              2.6 * np.cos( (263.2167 -  mj )*np.pi/180. ) + \
              2.7 * np.cos( ( 87.1450 -  2.0 * mj  +  2.0 * me )*np.pi/180. ) + \
              1.6 * np.cos( (109.4933 -  2.0 * mj  +  me )*np.pi/180. )
    sunlon += jupcorr

    # Allow for the Moon's perturbations using the mean elongation of
    # the Moon from the Sun D
    d = 350.7376814 + idlMod((445267.11422 * time), 360.0)
    mooncorr = 6.5 * np.sin(d * np.pi / 180.)
    sunlon += mooncorr

    # Allow for long period terms
    longterm = 6.4 * np.sin((231.19 + 20.20 * time) * np.pi / 180.)
    sunlon += longterm
    sunlon = idlMod((sunlon + 2592000.0), 1296000.0)
    longmed = sunlon / 3600.0

    # Allow for Aberration
    sunlon -= 20.5

    # Allow for Nutation using the longitude of the Moons mean node OMEGA
    omega = 259.183275 - idlMod((1934.142008 * time), 360.0)
    sunlon = sunlon - 17.2 * np.sin(omega * np.pi / 180.)

    # Calculate the True Obliquity
    oblt = 23.452294 - 0.0130125 * time + (
        9.2 * np.cos(omega * np.pi / 180.)) / 3600.0

    # Right Ascension and Declination
    sunlon /= 3600.0
    ra = np.arctan2(
        np.sin(sunlon * np.pi / 180.) * np.cos(oblt * np.pi / 180.),
        np.cos(sunlon * np.pi / 180.))

    neg = np.where(ra < 0.0)[0]
    nneg = len(neg)
    if nneg > 0: ra[neg] += 2.0 * np.pi

    dec = np.arcsin(
        np.sin(sunlon * np.pi / 180.) * np.sin(oblt * np.pi / 180.))

    if radian:
        oblt *= (np.pi / 180.)
        longmed *= (np.pi / 180.)
    else:
        ra /= (np.pi / 180.)
        dec /= (np.pi / 180.)

    jd = time * 36525.0 + 2415020.0

    if outfile is not None:
        # Write results to a file
        of = open(outfile, 'w')
        of.write("# File created by 'sunpos'\n")
        if not full_output:
            of.write("# 1) JD, 2) ra, 3) dec\n")
            np.savetxt(of, np.transpose(np.vstack((jd, ra, dec))))
        else:
            of.write("# 1) JD, 2) ra, 3) dec, 4) longitude, 5) obliquity\n")
            np.savetxt(of, np.transpose(np.vstack(
                (jd, ra, dec, longmed, oblt))))
        of.close()

    if plot:
        if not _ic.check["matplotlib"]:
            raise(PE.PyARequiredImport("Could not import matplotlib.", \
                  where="sunpos", \
                  solution=["Install matplotlib", "Switch `plot` flag to False."]))
        import matplotlib.pylab as plt
        plt.plot(jd, ra, 'k-', label="RA")
        plt.plot(jd, dec, 'g-', label="DEC")
        plt.legend()
        plt.show()

    if full_output:
        return jd, ra, dec, longmed, oblt
    else:
        return jd, ra, dec
Ejemplo n.º 28
0
def transitVisibilityPlot(allData, markTransit=False, plotLegend=True, showMoonDist=True, print2file=False):
    """
    Plot the visibility of transits.

    This function can conveniently be used with the output of
    the transitTimes function.

    Parameters
    ----------
    allData : dictionary
        Essentially the output of `transitTimes`.
        A dictionary mapping consecutive numbers (one per transit) to
        another dictionary providing the following keys:

          ============    ====================================================
          Key             Description
          ------------    ----------------------------------------------------
          Planet name     Name of the planet
          Transit jd      (Only if `markTransit is True)
                          Array giving JD of start, mid-time, and end of
                          transit.
          Obs jd          Array specifying the HJD of the start, center and
                          end of the observation.
          Obs cal         Equivalent to 'Obs jd', but in the form of the
                          calendar date. In particular, for each date, a list
                          containing [Year, month, day, fractional hours]
                          is given.
          Obs coord       East longitude [deg], latitude [deg], and
                          altitude [m] of the observatory.
          Star ra         Right ascension of the star [deg].
          Star dec        Declination of the star [deg].
          ============    ====================================================

        .. note:: To use the list created by transitTimes, the LONGITUDE and LATITUDE
                  of the observatory location must have been specified.
    markTransit : boolean, optional
        If True (default is False), the in-transit times will
        be clearly indicated in the plot.
        Note that this would not be the case otherwise, which is particularly
        important if extra off-transit time before and after the transit has been
        requested. 
    showMoonDist : boolean, optional
        If True (default), the Moon distance will be shown.
    print2file : boolean or string, optional
        If True, the plot will be dumped to a png-file named:
        "transitVis-"[planetName].png. The default is False. If a string is given,
        it specifies the name of the output file.
    """
    from PyAstronomy.pyasl import _ic
    if not _ic.check["matplotlib"]:
        raise(PE.PyARequiredImport("matplotlib is not installed.",
                                   where="transitVisibilityPlot",
                                   solution="Install matplotlib (http://matplotlib.org/)"))

    import matplotlib
    import matplotlib.pylab as plt
    from mpl_toolkits.axes_grid1 import host_subplot
    from matplotlib.ticker import MultipleLocator
    from matplotlib.font_manager import FontProperties
    from matplotlib import rcParams

    rcParams['xtick.major.pad'] = 12

    if len(allData) == 0:
        raise(PE.PyAValError("Input dictionary is empty",
                             where="transitVisibilityPlot",
                             solution=["Use `transitTimes` to generate input dictionary",
                                       "Did you forget to supply observer's location?",
                                       "If you used `transitTime`, you might need to change the call argument (e.g., times)"]))

    # Check whether all relevant data have been specified
    reqK = ["Obs jd", "Obs coord", "Star ra",
            "Star dec", "Obs cal", "Planet name"]
    if markTransit:
        reqK.append("Transit jd")
    missingK = []
    for k in reqK:
        if not k in allData[1]:
            missingK.append(k)
    if len(missingK) > 0:
        raise(PE.PyAValError("The following keys are missing in the input dictionary: " + ', '.join(missingK),
                             where="transitVisibilityPlot",
                             solution="Did you specify observer's location in `transitTimes`?"))

    fig = plt.figure(figsize=(15, 10))
    fig.subplots_adjust(left=0.07, right=0.8, bottom=0.15, top=0.88)
    ax = host_subplot(111)

    font0 = FontProperties()
    font1 = font0.copy()
    font0.set_family('sans-serif')
    font0.set_weight('light')
    font1.set_family('sans-serif')
    font1.set_weight('medium')

    for n in six.iterkeys(allData):
        # JD array
        jdbinsize = 1.0 / 24. / 10.
        jds = np.arange(allData[n]["Obs jd"][0],
                        allData[n]["Obs jd"][2], jdbinsize)
        # Get JD floating point
        jdsub = jds - np.floor(jds[0])
        # Get alt/az of object
        altaz = eq2hor.eq2hor(jds, np.ones(jds.size) * allData[n]["Star ra"], np.ones(jds.size) * allData[n]["Star dec"],
                              lon=allData[n]["Obs coord"][0], lat=allData[n]["Obs coord"][1],
                              alt=allData[n]["Obs coord"][2])
        # Get alt/az of Sun
        sunpos_altaz = eq2hor.eq2hor(jds, np.ones(jds.size) * allData[n]["Sun ra"], np.ones(jds.size) * allData[n]["Sun dec"],
                                     lon=allData[n]["Obs coord"][0], lat=allData[n]["Obs coord"][1],
                                     alt=allData[n]["Obs coord"][2])

        # Define plot label
        plabel = "[%02d]  %02d.%02d.%4d" % (n, allData[n]["Obs cal"][0][2],
                                            allData[n]["Obs cal"][0][1], allData[n]["Obs cal"][0][0])

        # Find periods of: day, twilight, and night
        day = np.where(sunpos_altaz[0] >= 0.)[0]
        twi = np.where(np.logical_and(
            sunpos_altaz[0] > -18., sunpos_altaz[0] < 0.))[0]
        night = np.where(sunpos_altaz[0] <= -18.)[0]

        if (len(day) == 0) and (len(twi) == 0) and (len(night) == 0):
            print()
            print("transitVisibilityPlot - no points to draw for date %2d.%2d.%4d"
                  % (allData[n]["Obs cal"][0][2], allData[n]["Obs cal"][0][1], allData[n]["Obs cal"][0][0]))
            print("Skip transit and continue with next")
            print()
            continue

        mpos = moonpos(jds)
        mpha = moonphase(jds)
        mpos_altaz = eq2hor.eq2hor(jds, mpos[0], mpos[1], lon=allData[n]["Obs coord"][0],
                                   lat=allData[n]["Obs coord"][1], alt=allData[n]["Obs coord"][2])
        moonind = np.where(mpos_altaz[0] > 0.)[0]

        if showMoonDist:
            mdist = getAngDist(mpos[0], mpos[1], np.ones(jds.size) * allData[n]["Star ra"],
                               np.ones(jds.size) * allData[n]["Star dec"])
            bindist = int((2.0 / 24.) / jdbinsize)
            firstbin = np.random.randint(0, bindist)
            for mp in range(0, int(len(jds) / bindist)):
                bind = int(firstbin + float(mp) * bindist)
                ax.text(jdsub[bind], altaz[0][bind] - 1., str(int(mdist[bind])) + r"$^\circ$", ha="center", va="top",
                        fontsize=8, stretch='ultra-condensed', fontproperties=font0, alpha=1.)

        if markTransit:
            # Mark points within transit. These may differ from that pertaining to the
            # observation if an extra offset was given to provide off-transit time.
            transit_only_ind = np.where(np.logical_and(jds >= allData[n]["Transit jd"][0],
                                                       jds <= allData[n]["Transit jd"][2]))[0]
            ax.plot(jdsub[transit_only_ind], altaz[0]
                    [transit_only_ind], 'g', linewidth=6, alpha=.3)

        if len(twi) > 1:
            # There are points in twilight
            linebreak = np.where(
                (jdsub[twi][1:] - jdsub[twi][:-1]) > 2.0 * jdbinsize)[0]
            if len(linebreak) > 0:
                plotrjd = np.insert(jdsub[twi], linebreak + 1, np.nan)
                plotdat = np.insert(altaz[0][twi], linebreak + 1, np.nan)
                ax.plot(plotrjd, plotdat, "-", color='#BEBEBE', linewidth=1.5)
            else:
                ax.plot(jdsub[twi], altaz[0][twi], "-",
                        color='#BEBEBE', linewidth=1.5)

        ax.plot(jdsub[night], altaz[0][night],
                'k', linewidth=1.5, label=plabel)
        ax.plot(jdsub[day], altaz[0][day], color='#FDB813', linewidth=1.5)

        altmax = np.argmax(altaz[0])
        ax.text(jdsub[altmax], altaz[0][altmax], str(n), color="b", fontsize=14,
                fontproperties=font1, va="bottom", ha="center")

        if n == 29:
            ax.text(1.1, 1.0 - float(n) * 0.04, "too many transits", ha="left", va="top", transform=ax.transAxes,
                    fontsize=10, fontproperties=font0, color="r")
        else:
            ax.text(1.1, 1.0 - float(n) * 0.04, plabel, ha="left", va="top", transform=ax.transAxes,
                    fontsize=12, fontproperties=font0, color="b")

    ax.text(1.1, 1.03, "Start of observation", ha="left", va="top", transform=ax.transAxes,
            fontsize=12, fontproperties=font0, color="b")
    ax.text(1.1, 1.0, "[No.]  Date", ha="left", va="top", transform=ax.transAxes,
            fontsize=12, fontproperties=font0, color="b")

    axrange = ax.get_xlim()
    ax.set_xlabel("UT [hours]")

    if axrange[1] - axrange[0] <= 1.0:
        jdhours = np.arange(0, 3, 1.0 / 24.)
        utchours = (np.arange(0, 72, dtype=int) + 12) % 24
    else:
        jdhours = np.arange(0, 3, 1.0 / 12.)
        utchours = (np.arange(0, 72, 2, dtype=int) + 12) % 24
    ax.set_xticks(jdhours)
    ax.set_xlim(axrange)
    ax.set_xticklabels(utchours, fontsize=18)

    # Make ax2 responsible for "top" axis and "right" axis
    ax2 = ax.twin()
    # Set upper x ticks
    ax2.set_xticks(jdhours)
    ax2.set_xticklabels(utchours, fontsize=18)
    ax2.set_xlabel("UT [hours]")

    # Horizon angle for airmass
    airmass_ang = np.arange(5., 90., 5.)
    geo_airmass = airmass.airmassPP(90. - airmass_ang)
    ax2.set_yticks(airmass_ang)
    airmassformat = []
    for t in range(geo_airmass.size):
        airmassformat.append("%2.2f" % geo_airmass[t])
    ax2.set_yticklabels(airmassformat, rotation=90)
    ax2.set_ylabel("Relative airmass", labelpad=32)
    ax2.tick_params(axis="y", pad=10, labelsize=10)
    plt.text(1.015, -0.04, "Plane-parallel", transform=ax.transAxes, ha='left',
             va='top', fontsize=10, rotation=90)

    ax22 = ax.twin()
    ax22.set_xticklabels([])
    ax22.set_frame_on(True)
    ax22.patch.set_visible(False)
    ax22.yaxis.set_ticks_position('right')
    ax22.yaxis.set_label_position('right')
    ax22.spines['right'].set_position(('outward', 25))
    ax22.spines['right'].set_color('k')
    ax22.spines['right'].set_visible(True)
    airmass2 = np.array([airmass.airmassSpherical(
        90. - ang, allData[n]["Obs coord"][2]) for ang in airmass_ang])
    ax22.set_yticks(airmass_ang)
    airmassformat = []
    for t in range(airmass2.size):
        airmassformat.append("%2.2f" % airmass2[t])
    ax22.set_yticklabels(airmassformat, rotation=90)
    ax22.tick_params(axis="y", pad=10, labelsize=10)
    plt.text(1.045, -0.04, "Spherical+Alt", transform=ax.transAxes, ha='left', va='top',
             fontsize=10, rotation=90)

    ax3 = ax.twiny()
    ax3.set_frame_on(True)
    ax3.patch.set_visible(False)
    ax3.xaxis.set_ticks_position('bottom')
    ax3.xaxis.set_label_position('bottom')
    ax3.spines['bottom'].set_position(('outward', 50))
    ax3.spines['bottom'].set_color('k')
    ax3.spines['bottom'].set_visible(True)

    ltime, ldiff = localtime.localTime(utchours, np.repeat(
        allData[n]["Obs coord"][0], len(utchours)))
    jdltime = jdhours - ldiff / 24.
    ax3.set_xticks(jdltime)
    ax3.set_xticklabels(utchours)
    ax3.set_xlim([axrange[0], axrange[1]])
    ax3.set_xlabel("Local time [hours]")

    ax.yaxis.set_major_locator(MultipleLocator(15))
    ax.yaxis.set_minor_locator(MultipleLocator(5))
    yticks = ax.get_yticks()
    ytickformat = []
    for t in range(yticks.size):
        ytickformat.append(str(int(yticks[t])) + r"$^\circ$")
    ax.set_yticklabels(ytickformat, fontsize=20)
    ax.set_ylabel("Altitude", fontsize=18)
    yticksminor = np.array(ax.get_yticks(minor=True))
    ymind = np.where(yticksminor % 15. != 0.)[0]
    yticksminor = yticksminor[ymind]
#     ax.set_yticks(yticksminor, minor=True)
    m_ytickformat = []
    for t in range(yticksminor.size):
        m_ytickformat.append(str(int(yticksminor[t])) + r"$^\circ$")
    ax.set_yticklabels(m_ytickformat, minor=True)

    ax.yaxis.grid(color='gray', linestyle='dashed')
    ax.yaxis.grid(color='gray', which="minor", linestyle='dotted')
    ax2.xaxis.grid(color='gray', linestyle='dotted')

    def decifnec(s):
        try:
            r = s.decode("utf8")
        except AttributeError:
            r = s
        return r
            
    plt.text(0.5, 0.95, "Transit visibility of " + decifnec(allData[n]["Planet name"]),
             transform=fig.transFigure, ha='center', va='bottom', fontsize=20)

    if plotLegend:
        line1 = matplotlib.lines.Line2D(
            (0, 0), (1, 1), color='#FDB813', linestyle="-", linewidth=2)
        line2 = matplotlib.lines.Line2D(
            (0, 0), (1, 1), color='#BEBEBE', linestyle="-", linewidth=2)
        line3 = matplotlib.lines.Line2D(
            (0, 0), (1, 1), color='k', linestyle="-", linewidth=2)
        line4 = matplotlib.lines.Line2D(
            (0, 0), (1, 1), color='g', linestyle="-", linewidth=6, alpha=.3)

        if markTransit:
            lgd2 = plt.legend((line1, line2, line3, line4), ("day", "twilight", "night", "transit",),
                              bbox_to_anchor=(0.88, 0.15), loc=2, borderaxespad=0., prop={'size': 12}, fancybox=True)
        else:
            lgd2 = plt.legend((line1, line2, line3), ("day", "twilight", "night",),
                              bbox_to_anchor=(0.88, 0.13), loc=2, borderaxespad=0., prop={'size': 12}, fancybox=True)
        lgd2.get_frame().set_alpha(.5)

    targetco = r"Target coordinates: (%8.4f$^\circ$, %8.4f$^\circ$)" % \
        (allData[n]["Star ra"], allData[n]["Star dec"])
    obsco = "Obs coord.: (%8.4f$^\circ$, %8.4f$^\circ$, %4d m)" % \
            (allData[n]["Obs coord"][0], allData[n]
             ["Obs coord"][1], allData[n]["Obs coord"][2])
    plt.text(0.01, 0.97, targetco, transform=fig.transFigure,
             ha='left', va='center', fontsize=10)
    plt.text(0.01, 0.95, obsco, transform=fig.transFigure,
             ha='left', va='center', fontsize=10)

    if (print2file == True): 
        outfile = "transVis-" + \
            str(allData[n]["Planet name"]).replace(" ", "") + ".png"
        plt.savefig(outfile, format="png", dpi=300)
    elif isinstance(print2file, six.string_types):
        plt.savefig(print2file, format="png", dpi=300)
    else:
        plt.show()
Ejemplo n.º 29
0
def estimateSNR(x, y, xlen, deg=1, controlPlot=False, xlenMode="dataPoints"):
  """
    Estimate Signal to Noise Ratio (SNR) in a data set.
    
    This function provides a simple algorithm to estimate
    the SNR in a data set. The algorithm subdivides the
    data set into sections with a length determined by the
    `xlen` parameter. Each individual subsection is
    fitted using a polynomial of degree `deg`. The SNR
    is then computed by assuming that the resulting
    chi square value is properly distributed according
    to the chi-square distribution.
    
    Parameters
    ----------
    x : array
        The abscissa values.
    y : array
        The ordinate values.
    xlen : int or float
        Length of the data subsection considered
        in the computation of the SNR. Whether `xlen`
        refers to the number of data points or a fixed
        subsection of the abscissa is determined by the
        `xlenMode` flag.
    deg : int, optional
        Degree of the polynomial used to fit the
        subsection of the data set. The default is
        one.
    controlPlot : boolean, optional
        If True, a control plot will be shown to
        verify the validity of the estimate.
    xlenMode : string, {"dataPoints", "excerpt", "all"}, optional
        Determines whether `xlen` refers to data points
        or a fixed length scale on the abscissa. If 'all' is specified,
        all available data will be used in the estimation.
    
    Returns
    -------
    SNR : dictionary
        Contains the SNR estimate for the individual subsections (key 'snrs')
        and the final SNR estimate (mean of all 'sub-SNRs', key 'SNR-Estimate').
  """
  # Stores the SNRs computed from the individual sections.
  snrs = []
  i = 0
  lastdof = None
  
  if controlPlot:
    try:
      import matplotlib.pylab as plt
    except ImportError:
      raise(PE.PyARequiredImport("Cannot import matplotlib.pylab", \
            where="estimateSNR", \
            solution=["Install matplotlib.", "Change `controlPlot` to False."]))
  
  while True:
    if xlenMode == "dataPoints":
      # xlen is given in units of data points
      indi = range(i*xlen, (i+1)*xlen)
      i += 1
      if i > len(x)/xlen: break
    elif xlenMode == "excerpt":
      # xlen is given in units of the abscissa values
      indi = np.where(np.logical_and(x >= i*float(xlen), x < (i+1)*float(xlen)))[0]
      i += 1
      if i*float(xlen) > max(x): break
    elif xlenMode == "all":
      if i > 1:
        break
      indi = range(len(x))
      i += 1
    else:
      raise(PE.PyAValError("Unknown xlenMode (" + str(xlenMode) + ").", \
                           solution = "Use either 'dataPoints' or 'excerpt'."))
    # Check whether indi is long enough
    if len(indi) <= (deg + 1):
      # Skip this subsection
      continue
    
    # Fit polynomial, calculate model and residuals
    poly = np.polyfit(x[indi], y[indi], deg)
    model = np.polyval(poly, x[indi])
    residuals = y[indi] - model
    
    # The number of "degrees of freedom)
    dof = len(indi) - (deg + 1)
    # Calculate reduced chi square ...
    stdEstimate = np.sqrt((residuals**2).sum() / dof)
    # A brute-force way to compute the expectation of sqrt(1/(X(d)/d)),
    # where X(d) is chi-square distributed with d degrees of freedom.
    if dof != lastdof:
      ccSample = np.random.chisquare(dof, 1000)
      corrFac = np.mean(np.sqrt(1.0/(ccSample / dof)))
      lastdof = dof
    stdEstimate *= corrFac 
    # ... and SNR
    snrs.append(np.mean(model) / stdEstimate)
    
    if controlPlot:
      if i == 1:
        # This is the first call
        ax1 = plt.subplot(3,1,1)
        plt.title("Data (blue) and model (red)")
        ax2 = plt.subplot(3,1,2, sharex=ax1)
        plt.title("Residuals")
        ax3 = plt.subplot(3,1,3, sharex=ax1)
        plt.title("SNR")
      # Create plot
      plt.subplot(3,1,1)
      plt.plot(x[indi], y[indi], 'b.')
      plt.plot(x[indi], model, 'r-')
      plt.subplot(3,1,2, sharex=ax1)
      plt.plot(x[indi], residuals, 'g.')
      plt.subplot(3,1,3, sharex=ax1)
      plt.plot(np.mean(x[indi]), snrs[-1], 'bp')
  
  if controlPlot:
    plt.show()
  
  return {"SNR-Estimate":np.mean(snrs), "snrs":snrs}
Ejemplo n.º 30
0
# Check Python version
_majV, _minV = sys.version_info[0:2]
if (_minV < 7) and (_majV == 2):
    PE.warn(
        "funcFit needs 2.7.x or greater. See documentation (Prerequisites) for explanation."
    )

ic = ImportCheck([
    "numpy", "scipy", "pymc", "matplotlib", "matplotlib.pylab", "pyfits",
    "emcee", "progressbar"
])

# Get out if numpy not present
if not ic.check["numpy"]:
    raise(PE.PyARequiredImport("Numpy cannot be imported.", solution="Install numpy (see http://numpy.scipy.org/, you probably should also install SciPy).", \
                               addInfo="The numpy package provides array support for Python and is indispensable in many scientific applications."))

# Check whether fitting modules can be imported
_scoImport = ic.check["scipy"]
_pymcImport = ic.check["pymc"]
_mplImport = ic.check["matplotlib"]

from PyAstronomy.funcFit.utils import *
from .modelRebin import turnIntoRebin, _ModelRebinDocu
from .onedfit import *
from .gauss1d import *
from .gauss2d import *
from .respModel import *
from .params import *
from .sinexp1d import *
from .polyModel import *