1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
|
"""Generate the area definition list restructuredtext document.
This should be run once before generating the sphinx documentation to
produce the ``area_def_list.rst`` file referenced by
``satpy/resample/__init__.py``.
"""
import logging
import pathlib
import sys
from datetime import datetime
import bokeh
import geoviews as gv
import geoviews.feature as gf
from bokeh.embed import components
from jinja2 import Template
from pyresample._formatting_html import _load_static_files
from pyresample.area_config import area_repr, load_area
from pyresample.utils.proj4 import ignore_pyproj_proj_warnings
from reader_table import rst_table_header, rst_table_row
from satpy.area import get_area_file
logger = logging.getLogger(__name__)
gv.extension("bokeh")
TEMPLATE = '''
{{ table_header }}
{% for area_name, area_def in areas.items() if area_def._repr_html_ is defined %}
{{ create_table_row(area_name, area_def) }}
{% endfor %}
.. raw:: html
{{ resources | indent(5) }}
{{ pyr_icons_svg | indent(5) }}
<style>
{{ pyr_css_style | indent(5) }}
</style>
{{ script | indent(5)}}
{% for area_name, area_div in area_divs_dict.items() %}
{{ area_name }}
{{ rst_underline('^', area_name|length) }}
.. raw:: html
{{ area_repr(areas[area_name], map_content=area_div, include_header=False, include_static_files=False) |
indent(5) }}
<br>
{% endfor %}
''' # noqa: Q001
def main():
"""Parse CLI arguments and generate area definition list file."""
from argparse import ArgumentParser
parser = ArgumentParser(description="Generate restructuredtext area definition list for sphinx documentation")
parser.add_argument("--area-file",
help="Input area YAML file to read")
parser.add_argument("-o", "--output-file",
type=pathlib.Path,
help="HTML or restructuretext filename to create. "
"Defaults to 'area_def_list.rst' in the "
"documentation source directory.")
args = parser.parse_args()
logging.basicConfig(level=logging.INFO)
if args.output_file is None:
args.output_file = str(pathlib.Path(__file__).resolve().parent / "area_def_list.rst")
area_file = args.area_file
if area_file is None:
area_file = get_area_file()[0]
area_list = load_area(area_file)
areas_dict = {_area_name(area): area for area in area_list}
logger.info(f"Generating bokeh plots ({datetime.now()})...")
script, divs_dict = _generate_html_map_divs(areas_dict)
logger.info(f"Done generating bokeh plots ({datetime.now()})")
def rst_underline(ch, num_chars):
return ch * num_chars
template = Template(TEMPLATE)
icons_svg, css_style = _load_static_files()
logger.info(f"Rendering document ({datetime.now()})...")
res = template.render(
resources=bokeh.resources.CDN.render(),
script=script,
area_divs_dict=divs_dict,
areas=areas_dict,
rst_underline=rst_underline,
area_repr=area_repr,
pyr_icons_svg=icons_svg,
pyr_css_style=css_style,
table_header=rst_table_header("Area Definitions", header=["Name", "Description", "Projection"],
widths="auto", class_name="area-table"),
create_table_row=_area_table_row,
)
logger.info(f"Done rendering document ({datetime.now()})")
with open(args.output_file, mode="w") as f:
f.write(res)
def _area_name(area_def) -> str:
if hasattr(area_def, "attrs"):
# pyresample 2
return area_def.attrs["name"]
# pyresample 1
return area_def.area_id
def _area_table_row(area_name, area_def):
with ignore_pyproj_proj_warnings():
area_proj = area_def.proj_dict.get("proj")
return rst_table_row([f"`{area_name}`_", area_def.description, area_proj])
def _generate_html_map_divs(areas_dict: dict) -> tuple[str, dict]:
areas_bokeh_models = {}
for area_name, area_def in areas_dict.items():
if not hasattr(area_def, "to_cartopy_crs"):
logger.info(f"Skipping {area_name} because it can't be converted to cartopy CRS")
continue
crs = area_def.to_cartopy_crs()
features = gv.Overlay([gf.ocean, gf.land, gf.borders, gf.coastline])
f = gv.render(
features.opts(
toolbar=None,
default_tools=[],
projection=crs,
xlim=crs.bounds[:2],
ylim=crs.bounds[2:],
),
backend="bokeh")
areas_bokeh_models[area_name] = f
script, divs_dict = components(areas_bokeh_models)
return script, divs_dict
if __name__ == "__main__":
sys.exit(main())
|