Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adding support for handling mersi3 data #91

Merged
merged 7 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ agency specific level-1 formats. So far, supports

- EUMETSAT Meteosat Second Generation SEVIRI HRIT level-1.5
- NOAA AVHRR GAC
- MERSI-2 level-1
- MERSI-2/3 level-1
- MODIS level-1
- AVHRR eps level-1b
- AVHRR AAPP level-1b
- VIIRS level-1b
- SLSTR level-1b
- EPS-SG MetImage level-1 test data
- EUMETSAT AVHRR GAC FDR
- EUMETSAT AVHRR GAC FDR
8 changes: 4 additions & 4 deletions bin/mersi22pps.py → bin/mersi2pps.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,17 @@
"""Script to convert MERSI-2 level-1 to PPS level-1c format using Pytroll/Satpy."""

import argparse
from level1c4pps.mersi22pps_lib import process_one_scene
from level1c4pps.mersi2pps_lib import process_one_scene


if __name__ == "__main__":
""" Create PPS-format level1c data
From a list of MERSI-2 level-1 files create a NWCSAF/PPS formatet level1c file for pps.
From a list of MERSI-2/3 level-1 files create a NWCSAF/PPS formatet level1c file for pps.
"""
parser = argparse.ArgumentParser(
description=('Script to produce a PPS-level1c file for a MERSI-2 level-1 scene'))
description=('Script to produce a PPS-level1c file for a MERSI-2/3 level-1 scene'))
parser.add_argument('files', metavar='fileN', type=str, nargs='+',
help='List of MERSI-2 files to process')
help='List of MERSI-2/3 files to process')
parser.add_argument('-o', '--out_dir', type=str, nargs='?',
required=False, default='.',
help="Output directory where to store the level1c file")
Expand Down
2 changes: 1 addition & 1 deletion level1c4pps/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ def convert_angles(scene, delete_azimuth=False):
'sunazimuth': np.array([-18000, 18000], dtype='int16'),
'satazimuth': np.array([-18000, 18000], dtype='int16'),
},
'mersi2_file_key': {
'mersi_file_key': {
'sunzenith': 'Geolocation/SolarZenithAngle',
'satzenith': 'Geolocation/SensorZenithAngle',
'azimuthdiff': 'Geolocation/SensorSolarAzimuthDifference',
Expand Down
134 changes: 0 additions & 134 deletions level1c4pps/mersi22pps_lib.py

This file was deleted.

139 changes: 139 additions & 0 deletions level1c4pps/mersi2pps_lib.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (c) 2019 level1c4pps developers
#
# This file is part of level1c4pps
#
# level1c4pps 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.
#
# level1c4pps 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 level1c4pps. If not, see <http://www.gnu.org/licenses/>.
# Author(s):

# Martin Raspaud <[email protected]>
# Nina Hakansson <[email protected]>
# Adam.Dybbroe <[email protected]>
# Bengt.Rydberg >[email protected]>

"""Functions to convert MERSI-2/3 level-1 data to a NWCSAF/PPS level-1c formated netCDF/CF file."""

import logging
import os
import time

import numpy as np
from satpy.scene import Scene
from level1c4pps import (
ANGLE_ATTRIBUTES,
compose_filename,
convert_angles,
get_encoding,
get_header_attrs,
rename_latitude_longitude,
set_header_and_band_attrs_defaults,
update_angle_attributes,
)

# Example filenames:
# tf2019234102243.FY3D-X_MERSI_GEOQK_L1B.HDF
# tf2019234102243.FY3D-X_MERSI_GEO1K_L1B.HDF
# tf2019234102243.FY3D-X_MERSI_1000M_L1B.HDF
# tf2019234102243.FY3D-X_MERSI_0250M_L1B.HDF
#

logger = logging.getLogger('mersi2pps')

SENSOR = { # sensor associated to platform
'FY3D': 'mersi-2',
'FY3F': 'mersi-3',
'FY3H': 'mersi-3',
}
SATPY_READER = { # satpy reader associated to sensor
'mersi-2': 'mersi2_l1b',
'mersi-3': 'mersi3_l1b',
}
PPS_BAND_NAME = { # PPS band name associated to satpy band name
'3': 'ch_r06',
'4': 'ch_r09',
'5': 'ch_r13',
'6': 'ch_r16',
'20': 'ch_tb37',
'22': 'ch_tb73',
'23': 'ch_tb85',
'24': 'ch_tb11',
'25': 'ch_tb12',
}
GEOLOCATION_NAMES = [ # additional variables to load
'latitude',
'longitude',
'satellite_azimuth_angle',
'satellite_zenith_angle',
'solar_azimuth_angle',
'solar_zenith_angle',
]
REFL_BANDS = ['3', '4', '5', '6']
ONE_IR_CHANNEL = '24'
RESOLUTION = 1000 # [m]
LOW_TB = 1 # [K] very cold brightness temperature


def set_header_and_band_attrs(scene, band, orbit_n):
"""Set and delete some attributes."""
set_header_and_band_attrs_defaults(
scene, list(PPS_BAND_NAME), PPS_BAND_NAME, REFL_BANDS, band, orbit_n=orbit_n,
)
scene.attrs['source'] = "mersi2pps.py"


def remove_broken_data(scene):
"""Set bad data to nodata."""
for band in PPS_BAND_NAME:
if band not in REFL_BANDS and band in scene:
scene[band].data = np.where(scene[band].data < LOW_TB, np.nan, scene[band].data)


def get_sensor(scene_file):
"""Get sensor associated to the scene file."""
for platform, sensor in SENSOR.items():
if platform in scene_file:
return sensor
logger.info("Failed to determine sensor associated to scene file: '%s'", scene_file)
return None


def process_one_scene(scene_files, out_path, engine='h5netcdf', orbit_n=0):
"""Make level 1c files in PPS-format."""
tic = time.time()
sensor = get_sensor(os.path.basename(scene_files[0]))
reader = SATPY_READER[sensor]
scene = Scene(reader=reader, filenames=scene_files)
band_names = list(PPS_BAND_NAME)
scene.load(band_names + GEOLOCATION_NAMES, resolution=RESOLUTION)
remove_broken_data(scene)
band = scene[ONE_IR_CHANNEL]
set_header_and_band_attrs(scene, band, orbit_n)
rename_latitude_longitude(scene)
convert_angles(scene, delete_azimuth=True)
update_angle_attributes(scene, band)
for angle in ['sunzenith', 'satzenith', 'azimuthdiff']:
scene[angle].attrs['file_key'] = ANGLE_ATTRIBUTES['mersi_file_key'][angle]
filename=compose_filename(scene, out_path, instrument=sensor.replace('-', ''), band=band)
scene.save_datasets(
writer='cf',
filename=filename,
header_attrs=get_header_attrs(scene, band=band, sensor=sensor),
engine=engine,
include_lonlats=False,
flatten_attrs=True,
encoding=get_encoding(scene, band_names, PPS_BAND_NAME, chunks=None),
)
print(f"Saved file {os.path.basename(filename)} after {time.time() - tic:3.1f} seconds")
return filename
4 changes: 2 additions & 2 deletions level1c4pps/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
import unittest

from level1c4pps.tests import (test_angles, test_seviri2pps, test_gac2pps,
test_mersi22pps, test_modis2pps, test_slstr2pps,
test_mersi2pps, test_modis2pps, test_slstr2pps,
test_viirs2pps, test_eumgacfdr2pps,
test_avhrr2pps, test_init)

Expand All @@ -37,7 +37,7 @@ def suite():
mysuite.addTests(test_seviri2pps.suite())
mysuite.addTests(test_gac2pps.suite())
mysuite.addTests(test_eumgacfdr2pps.suite())
mysuite.addTests(test_mersi22pps.suite())
mysuite.addTests(test_mersi2pps.suite())
mysuite.addTests(test_modis2pps.suite())
mysuite.addTests(test_avhrr2pps.suite())
mysuite.addTests(test_slstr2pps.suite())
Expand Down
Loading
Loading