Compose Cartopy projective transformations

40 Views Asked by At

With this simple example:

from typing import NamedTuple

import cartopy.crs
import cartopy.feature.nightshade
import cartopy.mpl.geoaxes
from matplotlib import pyplot as plt


class Hemisphere(NamedTuple):
    coord: tuple[float, float]
    crs: cartopy.crs.Orthographic
    ax: cartopy.mpl.geoaxes.GeoAxes

    @classmethod
    def make(
        cls,
        coord: tuple[float, float],
        figure: plt.Figure,
    ) -> 'Hemisphere':
        crs = cartopy.crs.Orthographic(
            central_longitude=coord[0],
            central_latitude=coord[1],
        )
        ax = figure.add_subplot(projection=crs)
        return cls(coord=coord, crs=crs, ax=ax)

    def plot(
        self,
        night: cartopy.feature.nightshade.Nightshade,
    ) -> None:
        self.ax.stock_img()
        self.ax.add_feature(night)
        self.ax.gridlines()


def plot(
    home_coord: tuple[float, float],
) -> plt.Figure:
    fig: plt.Figure = plt.figure()
    home_hemi = Hemisphere.make(coord=home_coord, figure=fig)
    night = cartopy.feature.nightshade.Nightshade()
    home_hemi.plot(night=night)
    return fig


def main() -> None:
    home_coord = -80, 40
    plot(home_coord=home_coord)
    plt.show()


if __name__ == '__main__':
    main()

shaded earth

I want to be able to rotate the depiction of the Earth such that the sunset-line is vertical, implying that the axial tilt of the Earth matches what it actually is in the solar system. I need to preserve scale and the location of home at the central_ point. Roughly this would look like

manually rotated

I believe this information to already be embedded in the calculations in Cartopy's nightshade.py - the Nightshade feature has a crs set to rotated_pole. Of course, if I initialise the axes to only use night.crs, then the shadow is correctly aligned but I lose my Orthographic:

shadow aligned

I want to compose the two and have an orthographic plot with the aligned sunset shadow. I've hunted around, and the closest I can find to composition in Cartopy is InterProjectionTransform, but this has several issues:

  • it isn't actually a Cartopy Projection, but instead a matplotlib Transform
  • it requires that you already have axes initialised - which means you can't use it to initialise axes.

I've looked, and there's no rotation angle parameter to Orthographic, nor does there seem to be the equivalent of an InterProjection for proper Cartopy projections.

I'd prefer to figure out something that uses Cartopy projection code if at all possible, avoiding mucking about in the lower matplotlib transformation code; though I don't know how practical that is. I'd also prefer to leverage what Nightshade has already done.

0

There are 0 best solutions below