diff --git a/doc/source/conf.py b/doc/source/conf.py index 271d3d23..32f902e6 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -259,6 +259,7 @@ def setup(app): "readers/avhrr.rst", "readers/clavrx.rst", "readers/mersi2_l1b.rst", + "readers/mersi_ll_l1b.rst", "readers/mirs.rst", "readers/modis_l1b.rst", "readers/modis_l2.rst", diff --git a/doc/source/readers/index.rst b/doc/source/readers/index.rst index ec3d1e3e..815aea30 100644 --- a/doc/source/readers/index.rst +++ b/doc/source/readers/index.rst @@ -28,6 +28,7 @@ using the ``--list-products`` option. :polar2grid:viirs_edr_active_fires :polar2grid:viirs_edr :polar2grid:mersi2_l1b + :polar2grid:mersi_ll_l1b :geo2grid:abi_l1b :geo2grid:abi_l2_nc :geo2grid:agri_fy4a_l1 diff --git a/doc/source/readers/mersi_ll_l1b.rst b/doc/source/readers/mersi_ll_l1b.rst new file mode 100644 index 00000000..de0d5e85 --- /dev/null +++ b/doc/source/readers/mersi_ll_l1b.rst @@ -0,0 +1,30 @@ +MERSI-2 L1B Reader +================== + +.. automodule:: polar2grid.readers.mersi_ll_l1b + :noindex: + +Command Line Arguments +---------------------- + +.. argparse:: + :module: polar2grid.readers.mersi_ll_l1b + :func: add_reader_argument_groups + :prog: polar2grid.sh -r mersi_ll_l1b -w + :passparser: + +Examples: + +.. code-block:: bash + + $POLAR2GRID_HOME/bin/polar2grid.sh -r mersi_ll_l1b -w geotiff -h + + polar2grid.sh -r mersi_ll_l1b -w geotiff --list-products -f tf2019259173245.FY3E-X_MERSI*.HDF + + polar2grid.sh -r mersi_ll_l1b -w geotiff -p 1 2 3 4 6 7 -f tf2019233172521.FY3E-X_MERSI_0250M_L1B.HDF tf2019233172521.FY3E-X_MERSI_1000M_L1B.HDF tf2019233172521.FY3E-X_MERSI_GEOQK_L1B.HDF tf2019233172521.FY3E-X_MERSI_GEO1K_L1B.HDF + + polar2grid.sh -r mersi_ll_l1b -w geotiff -p 1 2 -g lcc_fit -f ../mersi/tf2019259173245.FY3E-X_MERSI*.HDF + + polar2grid.sh -r mersi_ll_l1b -w hdf5 -p 3 4 5 --grid-configs ${HOME}/my_grid.yaml -g shanghai seoul -f ../data/*.HDF + + polar2grid.sh -r mersi_ll_l1b -w binary --sza-threshold=90 -p 1 -f tf2019226095418.FY3E-X_MERSI_*.HDF diff --git a/etc/resampling.yaml b/etc/resampling.yaml index 97827aaa..e8a8e4c7 100644 --- a/etc/resampling.yaml +++ b/etc/resampling.yaml @@ -278,3 +278,10 @@ resampling: kwargs: weight_delta_max: 40.0 weight_distance_max: 1.0 + default_mersill_l1b: + area_type: swath + reader: mersi_ll_l1b + resampler: ewa + kwargs: + weight_delta_max: 40.0 + weight_distance_max: 1.0 diff --git a/polar2grid/readers/mersi2_l1b.py b/polar2grid/readers/mersi2_l1b.py index 0e142b50..462e650f 100644 --- a/polar2grid/readers/mersi2_l1b.py +++ b/polar2grid/readers/mersi2_l1b.py @@ -20,19 +20,12 @@ # 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/ -# -# Written by William Roberts and David Hoese May 2019 -# University of Wisconsin-Madison -# Space Science and Engineering Center -# 1225 West Dayton Street -# Madison, WI 53706 -# wroberts4@wisc.edu and david.hoese@ssec.wisc.edu -"""The FY3-D MERSI2 Level 1B reader operates on Level 1B (L1B) HDF5 files. +"""The FY-3D MERSI2 Level 1B reader operates on Level 1B (L1B) HDF5 files. The files come in four varieties; band data and geolocation data, both at 250m and 1000m resolution. Files usually have the following naming scheme: - tf{start_time:%Y%j%H%M%S}.{platform_shortname}-{trans_band:1s}_MERSI_1000M_L1B.{ext} + tf{start_time:%Y%j%H%M%S}.FY3D-X_MERSI_1000M_L1B.{ext} This reader's default resampling algorithm is ``ewa`` for Elliptical Weighted Averaging resampling. The ``--weight-delta-max`` parameter is set to 40 and the diff --git a/polar2grid/readers/mersi_ll_l1b.py b/polar2grid/readers/mersi_ll_l1b.py new file mode 100644 index 00000000..dc73d8e4 --- /dev/null +++ b/polar2grid/readers/mersi_ll_l1b.py @@ -0,0 +1,116 @@ +# Copyright (C) 2023 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 . +# +# 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/ +"""The FY-3E MERSI-LL Level 1B reader operates on Level 1B (L1B) HDF5 files. + +The files come in four varieties; band data and geolocation data, both at 250m +and 1000m resolution. Files usually have the following naming scheme: + + tf{start_time:%Y%j%H%M%S}.FY3E-X_MERSI_1000M_L1B.{ext} + +This reader's default resampling algorithm is ``ewa`` for Elliptical Weighted +Averaging resampling. The ``--weight-delta-max`` parameter is set to 40 and the +``--weight-distance-max`` parameter is set to 1. + +The frontend can be specified with the ``polar2grid.sh`` command using +the ``mersi_ll_l1b`` frontend name. The MERSI-LL frontend provides the following products: + ++---------------------------+-----------------------------------------------------+-------------------------+ +| **Product Name** | **Description** | Central Wavelength (um) | ++===========================+=====================================================+=========================+ +| 1 | Channel 1 Day/Night Radiance Band | 0.709 | ++---------------------------+-----------------------------------------------------+-------------------------+ +| 2 | Channel 2 Brightness Temperature Band | 3.80 | ++---------------------------+-----------------------------------------------------+-------------------------+ +| 3 | Channel 3 Brightness Temperature Band | 4.05 | ++---------------------------+-----------------------------------------------------+-------------------------+ +| 4 | Channel 4 Brightness Temperature Band | 7.20 | ++---------------------------+-----------------------------------------------------+-------------------------+ +| 5 | Channel 5 Brightness Temperature Band | 8.55 | ++---------------------------+-----------------------------------------------------+-------------------------+ +| 6 | Channel 6 Brightness Temperature Band | 10.8 | ++---------------------------+-----------------------------------------------------+-------------------------+ +| 7 | Channel 7 Brightness Temperature Band | 12.0 | ++---------------------------+-----------------------------------------------------+-------------------------+ +| histogram_dnb | Histogram Equalized DNB Band | N/A | ++---------------------------+-----------------------------------------------------+-------------------------+ +| adaptive_dnb | Adaptive Histogram Equalized DNB Band | N/A | ++---------------------------+-----------------------------------------------------+-------------------------+ + +""" + +from __future__ import annotations + +from argparse import ArgumentParser, _ArgumentGroup +from typing import Optional + +from ._base import ReaderProxyBase + +ALL_BANDS = [str(x) for x in range(1, 8)] +ALL_ANGLES = [ + "solar_zenith_angle", + "solar_azimuth_angle", + "sensor_zenith_angle", + "sensor_azimuth_angle", + "moon_zenith_angle", + "moon_azimuth_angle", +] +ALL_COMPS = ["histogram_dnb", "adaptive_dnb"] + +# band 1 (DNB) is not useful by itself, histogram_dnb is not a default +DEFAULT_PRODUCTS = ALL_BANDS[1:] + ALL_COMPS[1:] + +PRODUCT_ALIASES = {} + +FILTERS = { + "day_only": { + "standard_name": [ + "toa_bidirectional_reflectance", + "true_color", + "false_color", + "natural_color", + ], + }, +} + + +class ReaderProxy(ReaderProxyBase): + """Provide Polar2Grid-specific information about this reader's products.""" + + is_polar2grid_reader = True + + def get_default_products(self) -> list[str]: + """Get products to load if users hasn't specified any others.""" + return DEFAULT_PRODUCTS + + def get_all_products(self) -> list[str]: + """Get all polar2grid products that could be loaded.""" + return ALL_BANDS + ALL_COMPS + ALL_ANGLES + + @property + def _aliases(self) -> dict: + return PRODUCT_ALIASES + + +def add_reader_argument_groups( + parser: ArgumentParser, group: Optional[_ArgumentGroup] = None +) -> tuple[Optional[_ArgumentGroup], Optional[_ArgumentGroup]]: + """Add reader-specific command line arguments to an existing argument parser.""" + return None, None