Source code for polar2grid.core.containers

#!/usr/bin/env python3
# encoding: utf-8
# Copyright (C) 2014-2021 Space Science and Engineering Center (SSEC),
# University of Wisconsin-Madison.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# This file is part of the polar2grid software package. Polar2grid takes
# satellite observation data, remaps it, and writes it to a file format for
#     input into another program.
# Documentation: http://www.ssec.wisc.edu/software/polar2grid/
"""Classes for metadata operations in polar2grid."""


[docs] class GridDefinition(dict): """Projected grid defined by a PROJ.4 projection string and other grid parameters. Required Information: - grid_name: Identifying name for the grid - proj4_definition (string): PROJ.4 projection definition - height: Height of the grid in number of pixels - width: Width of the grid in number of pixels - cell_height: Grid cell height in the projection domain (usually in meters or degrees) - cell_width: Grid cell width in the projection domain (usually in meters or degrees) - origin_x: X-coordinate of the upper-left corner of the grid in the projection domain - origin_y: Y-coordinate of the upper-left corner of the grid in the projection domain """ required_kwargs = ( "grid_name", "proj4_definition", "height", "width", "cell_height", "cell_width", "origin_x", "origin_y", ) def __init__(self, *args, **kwargs): if "proj4_definition" in kwargs: # pyproj doesn't like unicode kwargs["proj4_definition"] = str(kwargs["proj4_definition"]) super().__init__(*args, **kwargs) self.validate_keys()
[docs] def validate_keys(self): # sanity check, does this dictionary have everything the class expects it to for k in self.required_kwargs: if k not in self: raise ValueError("Missing required keyword '%s'" % (k,))
def __str__(self): keys = sorted(self.keys()) keys.insert(0, keys.pop(keys.index("height"))) keys.insert(0, keys.pop(keys.index("width"))) keys.insert(0, keys.pop(keys.index("cell_height"))) keys.insert(0, keys.pop(keys.index("cell_width"))) keys.insert(0, keys.pop(keys.index("proj4_definition"))) keys.insert(0, keys.pop(keys.index("grid_name"))) return "\n".join("%s: %s" % (k, self[k]) for k in keys) @property def is_static(self): return all( [self[x] is not None for x in ["height", "width", "cell_height", "cell_width", "origin_x", "origin_y"]] ) @property def xy_lowerleft(self): y_ll = self["origin_y"] + self["cell_height"] * (self["height"] - 1) return self["origin_x"], y_ll @property def xy_upperright(self): x_ll = self["origin_x"] + self["cell_width"] * (self["width"] - 1) return x_ll, self["origin_y"] @property def proj4_dict(self): parts = [x.replace("+", "") for x in self["proj4_definition"].split(" ")] no_defs = False if "no_defs" in parts: parts.remove("no_defs") no_defs = True over = False if "over" in parts: parts.remove("over") over = True proj4_dict = dict(p.split("=") for p in parts) # Convert numeric parameters to floats for k in [ "lat_0", "lat_1", "lat_2", "lat_ts", "lat_b", "lat_t", "lon_0", "lon_1", "lon_2", "lonc", "a", "b", "f", "es", "h", ]: if k in proj4_dict: proj4_dict[k] = float(proj4_dict[k]) # load information from PROJ.4 about the ellipsis if possible if "ellps" in proj4_dict and ("a" not in proj4_dict or "b" not in proj4_dict): import pyproj ellps = pyproj.pj_ellps[proj4_dict["ellps"]] proj4_dict["a"] = ellps["a"] if "b" not in ellps and "rf" in ellps: proj4_dict["f"] = 1.0 / ellps["rf"] else: proj4_dict["b"] = ellps["b"] if "a" in proj4_dict and "f" in proj4_dict and "b" not in proj4_dict: # add a "b" attribute back in if they used "f" instead proj4_dict["b"] = proj4_dict["a"] * (1 - proj4_dict["f"]) # Add removed keywords back in if no_defs: proj4_dict["no_defs"] = True if over: proj4_dict["over"] = True return proj4_dict @property def ll_extent(self): xy_ll = self.xy_lowerleft # NOTE: cell_height is negative return xy_ll[0] - self["cell_width"] / 2.0, xy_ll[1] + self["cell_height"] / 2.0 @property def ur_extent(self): xy_ur = self.xy_upperright # NOTE: cell_height is negative return xy_ur[0] + self["cell_width"] / 2.0, xy_ur[1] - self["cell_height"] / 2.0
[docs] def to_satpy_area(self): from pyresample.geometry import AreaDefinition, DynamicAreaDefinition if self.is_static: xy_ll = self.ll_extent xy_ur = self.ur_extent return AreaDefinition( self["grid_name"], self["grid_name"], self["grid_name"], self.proj4_dict, self["width"], self["height"], area_extent=xy_ll + xy_ur, ) kwargs = {} if self["cell_width"] is not None: kwargs["resolution"] = (abs(self["cell_width"]), abs(self["cell_height"])) return DynamicAreaDefinition( self["grid_name"], self["grid_name"], self.proj4_dict, self["width"], self["height"], **kwargs )