Skip to content

Commit 5146ff7

Browse files
Merge pull request #90 from salomoneliassonSMHI/SBAFsv3
Adding v3 SBAFs
2 parents 4d48a6a + 0142993 commit 5146ff7

File tree

5 files changed

+346
-133
lines changed

5 files changed

+346
-133
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
build
12
*py~
23
*pyc
34
*~

bin/vgac2pps.py

+10-5
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,12 @@
2121
# Martin Raspaud <martin.raspaud@smhi.se>
2222
# Nina Hakansson <nina.hakansson@smhi.se>
2323
# Adam.Dybbroe <adam.dybbroe@smhi.se>
24+
# Salomon.Eliasson <salomon.eliasson@smhi.se>
2425

2526
"""Script to convert VIIRS level-1 to PPS level-1c format using Pytroll/Satpy."""
2627

2728
import argparse
28-
from level1c4pps.vgac2pps_lib import process_one_scene
29+
from level1c4pps.vgac2pps_lib import SBAF, process_one_scene
2930

3031

3132
if __name__ == "__main__":
@@ -44,8 +45,11 @@
4445
help="Engine for saving netcdf files netcdf4 or h5netcdf (default).")
4546
parser.add_argument('-all_ch', '--all_channels', action='store_true',
4647
help="Save all 21 channels to level1c4pps file.")
47-
parser.add_argument('-n19', '--as_noaa19', action='store_true',
48-
help="Save only the AVHRR (1,2, 3B, 4, 5) channels to level1c4pps file. And apply SBAFs to the channels.")
48+
parser.add_argument('-n19', '--as_noaa19',
49+
options=[version for version in SBAF],
50+
default=None,
51+
help=("Save only the AVHRR (1,2, 3B, 4, 5) channels to level1c4pps file. "
52+
"And apply SBAFs to the channels."))
4953
parser.add_argument('-pps_ch', '--pps_channels', action='store_true',
5054
help="Save only the necessary (for PPS) channels to level1c4pps file.")
5155
parser.add_argument('-avhrr_ch', '--avhrr_channels', action='store_true',
@@ -58,5 +62,6 @@
5862
options = parser.parse_args()
5963
process_one_scene(options.files, options.out_dir, engine=options.nc_engine,
6064
all_channels=options.all_channels, pps_channels=options.pps_channels,
61-
orbit_n=options.orbit_number, as_noaa19=options.as_noaa19, avhrr_channels=options.avhrr_channels,
62-
split_files_at_midnight = not options.don_split_files_at_midnight)
65+
orbit_n=options.orbit_number, noaa19_sbaf_version=options.as_noaa19,
66+
avhrr_channels=options.avhrr_channels,
67+
split_files_at_midnight=not options.don_split_files_at_midnight)

level1c4pps/__init__.py

+11-8
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
from importlib.metadata import version
2626
import numpy as np
2727
import xarray as xr
28-
from datetime import datetime
28+
from datetime import datetime, timezone
2929
import os
3030
import logging
3131
import satpy
@@ -244,16 +244,16 @@ def centered_modulus(daz, divisor=360):
244244
def dt64_to_datetime(dt64):
245245
"""Conversion of numpy.datetime64 to datetime objects."""
246246
# https://stackoverflow.com/questions/13703720/converting-between-datetime-timestamp-and-datetime64/46921593#46921593
247-
if type(dt64) == np.datetime64:
247+
if type(dt64) is np.datetime64:
248248
unix_epoch = np.datetime64(0, 's')
249249
one_second = np.timedelta64(1, 's')
250250
seconds_since_epoch = (dt64 - unix_epoch) / one_second
251-
dt = datetime.utcfromtimestamp(seconds_since_epoch)
251+
dt = datetime.fromtimestamp(seconds_since_epoch, timezone.utc).replace(tzinfo=None)
252252
return dt
253-
elif type(dt64) == np.float64:
253+
elif type(dt64) is np.float64:
254254
seconds_since_epoch = dt64
255-
dt = datetime.utcfromtimestamp(seconds_since_epoch)
256-
return dt
255+
dt = datetime.fromtimestamp(seconds_since_epoch, timezone.utc).replace(tzinfo=None)
256+
return dt
257257
return dt64
258258

259259

@@ -341,7 +341,7 @@ def rename_latitude_longitude(scene):
341341
for alt_latname in ['lat_pixels', 'm_latitude', 'latitude_m', 'i_latitude']:
342342
if alt_latname in scene and 'latitude' not in scene:
343343
lat_name_satpy = alt_latname
344-
for alt_lonname in ['lon_pixels', 'm_longitude','longitude_m', 'i_longitude']:
344+
for alt_lonname in ['lon_pixels', 'm_longitude', 'longitude_m', 'i_longitude']:
345345
if alt_lonname in scene and 'longitude' not in scene:
346346
lon_name_satpy = alt_lonname
347347
scene[lat_name_satpy].attrs['name'] = 'lat'
@@ -565,12 +565,15 @@ def compose_filename(scene, out_path, instrument, band=None):
565565
return filename
566566

567567

568-
def get_header_attrs(scene, band, sensor='avhrr'):
568+
def get_header_attrs(scene, band, sensor='avhrr', sbaf_version='NO_SBAF'):
569569
"""Get global netcdf attributes."""
570570
header_attrs = scene.attrs.copy()
571571
header_attrs['start_time'] = datetime.strftime(dt64_to_datetime(band.attrs['start_time']),
572572
"%Y-%m-%d %H:%M:%S")
573573
header_attrs['end_time'] = datetime.strftime(dt64_to_datetime(band.attrs['end_time']),
574574
"%Y-%m-%d %H:%M:%S")
575575
header_attrs['sensor'] = sensor
576+
577+
header_attrs['sbaf_version'] = sbaf_version
578+
576579
return header_attrs

level1c4pps/tests/test_vgac2pps.py

+9-8
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
import netCDF4
2626
import unittest
27-
from datetime import datetime
27+
from datetime import datetime, timezone
2828
try:
2929
from unittest import mock
3030
except ImportError:
@@ -46,8 +46,8 @@ def setUp(self):
4646
ir_108 = mock.MagicMock(attrs={'name': 'image1',
4747
'id_tag': 'ch_tb11',
4848
'wavelength': [1, 2, 3, 'um'],
49-
'start_time': datetime.utcnow(),
50-
'end_time': datetime.utcnow(),
49+
'start_time': datetime.now(timezone.utc),
50+
'end_time': datetime.now(timezone.utc),
5151
'history': 'dummy',
5252
'platform_name': 'tirosn',
5353
'orbit_number': 99999})
@@ -97,7 +97,7 @@ def test_process_one_scene(self):
9797

9898
vgac2pps.process_one_scene(
9999
['./level1c4pps/tests/VGAC_VJ102MOD_A2018305_1042_n004946_K005.nc'],
100-
out_path='./level1c4pps/tests/',
100+
out_path='./level1c4pps/tests/'
101101
)
102102
filename = './level1c4pps/tests/S_NWC_viirs_noaa20_00000_20181101T1042080Z_20181101T1224090Z.nc'
103103
# written with hfnetcdf read with NETCDF4 ensure compatability
@@ -121,13 +121,14 @@ def test_process_one_scene(self):
121121

122122
np.testing.assert_almost_equal(pps_nc.variables['image1'].sun_earth_distance_correction_factor,
123123
1.0, decimal=4)
124+
124125
def test_process_one_scene_n19(self):
125126
"""Test process one scene for one example file."""
126127

127128
vgac2pps.process_one_scene(
128129
['./level1c4pps/tests/VGAC_VJ102MOD_A2018305_1042_n004946_K005.nc'],
129130
out_path='./level1c4pps/tests/',
130-
as_noaa19=True,
131+
noaa19_sbaf_version='v6'
131132
)
132133
filename = './level1c4pps/tests/S_NWC_avhrr_vgac20_00000_20181101T1042080Z_20181101T1224090Z.nc'
133134
filename_viirs = './level1c4pps/tests/S_NWC_viirs_noaa20_00000_20181101T1042080Z_20181101T1224090Z.nc'
@@ -155,14 +156,14 @@ def test_process_one_scene_n19(self):
155156
1.0, decimal=4)
156157

157158
np.testing.assert_equal(pps_nc.__dict__["platform"], "vgac20")
158-
self.assertTrue(np.abs(pps_nc.variables['image1'][0,0,0] - pps_nc_viirs.variables['image1'][0,0,0])>0.01)
159-
159+
self.assertTrue(np.abs(pps_nc.variables['image1'][0, 0, 0] - pps_nc_viirs.variables['image1'][0, 0, 0]) > 0.01)
160+
160161
def test_process_one_scene_midnight(self):
161162
"""Test process one scene for one example file."""
162163

163164
vgac2pps.process_one_scene(
164165
['./level1c4pps/tests/VGAC_VNPP02MOD_A2012365_2304_n06095_K005.nc'],
165-
out_path='./level1c4pps/tests/',
166+
out_path='./level1c4pps/tests/'
166167
)
167168
filename = './level1c4pps/tests/S_NWC_viirs_npp_00000_20121230T2359563Z_20121230T2359599Z.nc'
168169
# written with hfnetcdf read with NETCDF4 ensure compatability

0 commit comments

Comments
 (0)