Exemple #1
0
def plot_keplerian_orbit(a, per, ecc=0, t_p=0, OMEGA=180, omega=90, inc=90, R_main=1, R_sec=1, fig=None, show=True):
    """Plot a keplerian orbit.

    Show the orbit in the plan of the three planes: xy (plane of the sky), xz and yzselfself.
    Also show a zoom on the transit and eclipse regions.

    :param float      a: Semi-major axis [astropy Quantity/au]
    :param float    per: Orbital period [astropy Quantity/day]
    :param float    ecc: Orbital eccentricity (0-1)
    :param float    t_p: Time of periapsis passage [day]
    :param float  OMEGA: Longitude of the ascending node [astropy Quantity/deg]
    :param float  omega: Argument of periapsis [astropy Quantity/deg]
        Note that the longitude if periapsis is given by OMEGA + omega.
    :param float    inc: Orbit inclination [astropy Quantity/deg].
    :param float R_main: Radius of the main object (for ex. the star) [astropy Quantity/R_sun]
    :param float  R_sec: Radius of the secondary object (for ex. the planet) [astropy Quantity/R_jup]
    :param Figure  fig: Figure
    :param bool   show: If True show the figure before exiting the function
    """
    # Check parameters units
    d_par = {"a": a, "per": per, "ecc": ecc, "t_p": t_p, "OMEGA": OMEGA, "omega": omega, "inc": inc,
             "R_main": R_main, "R_sec": R_sec}
    for param, unit in zip(["a", "per", "t_p", "OMEGA", "omega", "inc", "R_main", "R_sec"],
                           [unt.au, unt.d, unt.d, unt.deg, unt.deg, unt.deg, unt.R_sun, unt.R_jup]):
        if isinstance(d_par[param], unt.Quantity):
            d_par[param] = d_par[param].to(unit).value
    # Main radius in AU
    R_main_au = d_par["R_main"] * unt.R_sun.to(unt.au)
    # Initialise the axes and figure
    if fig is None:
        # Create figure and axes
        fig, axes = pl.subplots(nrows=2, ncols=2)
        # Put labels and titles
        axes[1, 0].set_title("Plan of Sky - full xy")
        axes[1, 0].set_xlabel("x - East ->")
        axes[1, 0].set_ylabel("y - North ->")
        axes[0, 0].set_title("Plan xz")
        axes[1, 1].set_title("Plan zy")
        axes[0, 1].set_title("Plan of Sky - Eclipses Zoom")
        axes[0, 1].set_xlabel("x - East ->")
        axes[0, 1].set_ylabel("y - North ->")
        # Ensure equal scale axis
        for ax in axes.flat:
            ax.axis("equal")
    else:
        axes = array(fig.get_axes()).reshape((2, 2))
    # Create the Keplerian elliptical orbit
    # ke = KeplerEllipse(1, 10, e=0.0, Omega=180., i=90.0, w=90.0)
    ke = KeplerEllipse(d_par["a"], d_par["per"], e=d_par["ecc"], tau=d_par["t_p"], Omega=d_par["OMEGA"],
                       i=d_par["inc"], w=d_par["omega"])
    # Create a time vector to sample the full period
    time = linspace(t_p, t_p + per, 200)
    # Compute the position xyz for the time vector
    pos = ke.xyzPos(time)
    # Find the nodes of the orbit (Observer at -z)
    ascn, descn = ke.xyzNodes_LOSZ()
    # Plot the Main object
    for ax in axes.flat:
        star = pl.Circle((0, 0), radius=R_main_au, facecolor="C8", edgecolor="black")
        ax.add_artist(star)
    # Plot orbit in xy plans
    axes[1, 0].plot(pos[::, 0], pos[::, 1])
    # Plot orbit in xy plans Eclipses zoom
    axes[0, 1].plot(pos[::, 0], pos[::, 1])
    # Do the Zoom
    axes[0, 1].set_xlim((-R_main_au * 1.5, R_main_au * 1.5))
    axes[0, 1].set_ylim((-R_main_au * 1.5, R_main_au * 1.5))
    # Plot orbit in xz plan
    axes[0, 0].plot(pos[::, 0], pos[::, 2])
    # Plot orbit in zy plan
    axes[1, 1].plot(pos[::, 2], pos[::, 1])
    if show:
        pl.show()
    return fig
Exemple #2
0
class KeplerEllipseModel(fuf.OneDFit):
  """
    A model of a Keplerian orbit.
    
    This class uses the *KeplerEllipse* from the PyA's pyasl
    to calculate a Keplerian orbit. It may be used to fit
    complete 3d information on the orbit. Projections using
    only one or two dimensions are also possible.
    
    The constructor allows to specify *relevant axes*, which
    are those axes considered in the calculation. The actual
    model is, however, only one-dimensional. The values
    returned by evaluate have the order
    a1, b1, c1, a2, b2, c3, ... . Where a, b, and c stand for
    the first, second, and third axis and the number specifies
    the data point. Note that in this case, the resulting
    model has not the same number of points as the time
    axis.
    
    *Fit parameters*
      -  `a`    - The semi-major axis (same units as the data)
      - `per`   - The period (same time units as data)
      - `e`     - The eccentricity
      - `tau`   - Time of periapsis passage (same time units as data)
      - `Omega` - Longitude of the ascending node [deg]
      - `w`     - Argument of periapsis [deg]
      - `i`     - Inclination angle [deg]
    
    Parameters
    ----------
    relevantAxes : string
        A string containing any combination of x, y, and z.
        The string specifies the axes (and their order) to
        be considered in the calculations.
  """

  def __init__(self, relevantAxes="xyz"):
    self.ke = KeplerEllipse(1.0, 1.0)
    fuf.OneDFit.__init__(self, ["a", "per", "e", "tau", "Omega", "w", "i"])
    self["a"] = 1.0
    self["per"] = 1.0
    # Which axes to consider?
    # x=0, y=1, z=2
    self.axes = ()
    for i, axis in enumerate("xyz"):
      if axis in relevantAxes:
        self.axes += (i,)

  def evaluate(self, t):
    """
      Calculates and returns model according to the
      current parameter values.
      
      Although more than one axis may be relevant
      the output will be one dimensional. If, e.g.,
      the relevant axes are x and y, the order of
      the output will be x0, y0, x1, y1, ... .

      Parameters
      ----------
      t : array
          Times at which to evaluate the model.
    """
    self.ke.i = self["i"]
    self.ke.w = self["w"]
    self.ke.Omega = self["Omega"]
    self.ke.e = abs(self["e"])
    self.ke.a = self["a"]
    self.ke.per = self["per"]
    self.ke.tau = self["tau"]
    self.ke.n = 2.0*pi/self["per"]
    # Get the data pertaining to the relevant axes
    pos = self.ke.xyzPos(t)[::,self.axes]
    # Reshape to 1d form
    # If the relevant axes are x and y, the order
    # of the output will be x0, y0, x1, y1, x2, y2, ...
    pos = pos.reshape(pos.size)
    return pos
Exemple #3
0
class KeplerEllipseModel(fuf.OneDFit):
    """
    A model of a Keplerian orbit.
    
    This class uses the *KeplerEllipse* from the PyA's pyasl
    to calculate a Keplerian orbit. It may be used to fit
    complete 3d information on the orbit. Projections using
    only one or two dimensions are also possible.
    
    The constructor allows to specify *relevant axes*, which
    are those axes considered in the calculation. The actual
    model is, however, only one-dimensional. The values
    returned by evaluate have the order
    a1, b1, c1, a2, b2, c3, ... . Where a, b, and c stand for
    the first, second, and third axis and the number specifies
    the data point. Note that in this case, the resulting
    model has not the same number of points as the time
    axis.
    
    *Fit parameters*
      -  `a`    - The semi-major axis (same units as the data)
      - `per`   - The period (same time units as data)
      - `e`     - The eccentricity
      - `tau`   - Time of periapsis passage (same time units as data)
      - `Omega` - Longitude of the ascending node [deg]
      - `w`     - Argument of periapsis [deg]
      - `i`     - Inclination angle [deg]
    
    Parameters
    ----------
    relevantAxes : string
        A string containing any combination of x, y, and z.
        The string specifies the axes (and their order) to
        be considered in the calculations.
  """
    def __init__(self, relevantAxes="xyz"):
        self.ke = KeplerEllipse(1.0, 1.0)
        fuf.OneDFit.__init__(self, ["a", "per", "e", "tau", "Omega", "w", "i"])
        self["a"] = 1.0
        self["per"] = 1.0
        # Which axes to consider?
        # x=0, y=1, z=2
        self.axes = ()
        for i, axis in enumerate("xyz"):
            if axis in relevantAxes:
                self.axes += (i, )

    def evaluate(self, t):
        """
      Calculates and returns model according to the
      current parameter values.
      
      Although more than one axis may be relevant
      the output will be one dimensional. If, e.g.,
      the relevant axes are x and y, the order of
      the output will be x0, y0, x1, y1, ... .

      Parameters
      ----------
      t : array
          Times at which to evaluate the model.
    """
        self.ke.i = self["i"]
        self.ke.w = self["w"]
        self.ke.Omega = self["Omega"]
        self.ke.e = abs(self["e"])
        self.ke.a = self["a"]
        self.ke.per = self["per"]
        self.ke.tau = self["tau"]
        self.ke.n = 2.0 * pi / self["per"]
        # Get the data pertaining to the relevant axes
        pos = self.ke.xyzPos(t)[::, self.axes]
        # Reshape to 1d form
        # If the relevant axes are x and y, the order
        # of the output will be x0, y0, x1, y1, x2, y2, ...
        pos = pos.reshape(pos.size)
        return pos
class KeplerEllipseModel(fuf.OneDFit):
    """
    A model of a Keplerian orbit.

    This class uses the *KeplerEllipse* from the PyA's pyasl
    to calculate a Keplerian orbit. It may be used to fit
    complete 3d position or velocity information on the orbit;
    any individual axes may also be selected.

    The constructor allows to specify *relevant axes*, which
    are those axes considered in the calculation. The actual
    (technical) model is, however, only one-dimensional. The values
    returned by evaluate have the order
    a1, b1, c1, a2, b2, c3, ... . Where a, b, and c represent
    the first, second, and third axis and the number specifies
    the data point. Note that in this case, the resulting
    model has not the same number of points as the time
    axis.

    *Fit parameters*
      -  `a`    - The semi-major axis (same units as the data)
      - `per`   - The period (same time units as data)
      - `e`     - The eccentricity
      - `tau`   - Time of periapsis passage (same time units as data)
      - `Omega` - Longitude of the ascending node [deg]
      - `w`     - Argument of periapsis [deg]
      - `i`     - Inclination angle [deg]

    Parameters
    ----------
    relevantAxes : string
        A string containing any combination of x, y, and z.
        The string specifies the axes (and their order) to
        be considered in the calculations.
    mode : string, {"pos", "vel"}
        Determines whether the output is positions or
        velocities. In this case, the units are determined
        by the units of major axis and time (e.g., AU per day).
    """
    def __init__(self, relevantAxes="xyz", mode="pos"):
        self.ke = KeplerEllipse(1.0, 1.0)
        fuf.OneDFit.__init__(self, ["a", "per", "e", "tau", "Omega", "w", "i"])
        self["a"] = 1.0
        self["per"] = 1.0
        # Which axes to consider?
        # x=0, y=1, z=2
        self.axes = ()
        for i, axis in enumerate("xyz"):
            if axis in relevantAxes:
                self.axes += (i, )
        # Save the mode
        if not mode in ["pos", "vel"]:
            raise(PE.PyAValError("Unknown mode: " + str(mode), \
                                 where="KeplerEllipseModel", \
                                 solution="Choose either 'pos' or 'vel'."))
        self._mode = mode

    def evaluate(self, t):
        """
        Calculates and returns model according to the
        current parameter values.

        Although more than one axis may be relevant
        the output will be one dimensional. If, e.g.,
        the relevant axes are x and y, the order of
        the output will be x0, y0, x1, y1, ... .

        Parameters
        ----------
        t : array
            Times at which to evaluate the model.
        """
        self.ke.i = self["i"]
        self.ke.w = self["w"]
        self.ke.Omega = self["Omega"]
        self.ke.e = abs(self["e"])
        self.ke.a = self["a"]
        self.ke.per = self["per"]
        self.ke.tau = self["tau"]
        self.ke.n = 2.0 * pi / self["per"]
        # Get the data pertaining to the relevant axes
        if self._mode == "pos":
            result = self.ke.xyzPos(t)[::, self.axes]
        else:
            result = self.ke.xyzVel(t)[::, self.axes]
        # Reshape to 1d form
        # If the relevant axes are x and y, the order
        # of the output will be x0, y0, x1, y1, x2, y2, ...
        result = result.reshape(result.size)
        return result
class KeplerEllipseModel(fuf.OneDFit):
    """
    A model of a Keplerian orbit.

    This class uses the *KeplerEllipse* from the PyA's pyasl
    to calculate a Keplerian orbit. It may be used to fit
    complete 3d position or velocity information on the orbit;
    any individual axes may also be selected.

    The constructor allows to specify *relevant axes*, which
    are those axes considered in the calculation. The actual
    (technical) model is, however, only one-dimensional. The values
    returned by evaluate have the order
    a1, b1, c1, a2, b2, c3, ... . Where a, b, and c represent
    the first, second, and third axis and the number specifies
    the data point. Note that in this case, the resulting
    model has not the same number of points as the time
    axis.

    *Fit parameters*
      -  `a`    - The semi-major axis (same units as the data)
      - `per`   - The period (same time units as data)
      - `e`     - The eccentricity
      - `tau`   - Time of periapsis passage (same time units as data)
      - `Omega` - Longitude of the ascending node [deg]
      - `w`     - Argument of periapsis [deg]
      - `i`     - Inclination angle [deg]

    Parameters
    ----------
    relevantAxes : string
        A string containing any combination of x, y, and z.
        The string specifies the axes (and their order) to
        be considered in the calculations.
    mode : string, {"pos", "vel"}
        Determines whether the output is positions or
        velocities. In this case, the units are determined
        by the units of major axis and time (e.g., AU per day).
    """

    def __init__(self, relevantAxes="xyz", mode="pos"):
        self.ke = KeplerEllipse(1.0, 1.0)
        fuf.OneDFit.__init__(self, ["a", "per", "e", "tau", "Omega", "w", "i"])
        self["a"] = 1.0
        self["per"] = 1.0
        # Which axes to consider?
        # x=0, y=1, z=2
        self.axes = ()
        for i, axis in enumerate("xyz"):
            if axis in relevantAxes:
                self.axes += (i,)
        # Save the mode
        if not mode in ["pos", "vel"]:
            raise(PE.PyAValError("Unknown mode: " + str(mode), \
                                 where="KeplerEllipseModel", \
                                 solution="Choose either 'pos' or 'vel'."))
        self._mode = mode

    def evaluate(self, t):
        """
        Calculates and returns model according to the
        current parameter values.

        Although more than one axis may be relevant
        the output will be one dimensional. If, e.g.,
        the relevant axes are x and y, the order of
        the output will be x0, y0, x1, y1, ... .

        Parameters
        ----------
        t : array
            Times at which to evaluate the model.
        """
        self.ke.i = self["i"]
        self.ke.w = self["w"]
        self.ke.Omega = self["Omega"]
        self.ke.e = abs(self["e"])
        self.ke.a = self["a"]
        self.ke.per = self["per"]
        self.ke.tau = self["tau"]
        self.ke.n = 2.0 * pi / self["per"]
        # Get the data pertaining to the relevant axes
        if self._mode == "pos":
            result = self.ke.xyzPos(t)[::, self.axes]
        else:
            result = self.ke.xyzVel(t)[::, self.axes]
        # Reshape to 1d form
        # If the relevant axes are x and y, the order
        # of the output will be x0, y0, x1, y1, x2, y2, ...
        result = result.reshape(result.size)
        return result