From eb4b89c492b814daa5c595fce02111e3e9108635 Mon Sep 17 00:00:00 2001 From: "Adam.Dybbroe" Date: Thu, 1 Feb 2018 15:32:33 +0100 Subject: [PATCH 01/23] Bugfix viirs loading - picked from (xarray)develop branch Signed-off-by: Adam.Dybbroe --- satpy/readers/hdf5_utils.py | 6 +++++- satpy/readers/helper_functions.py | 18 +++++++++++++++--- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/satpy/readers/hdf5_utils.py b/satpy/readers/hdf5_utils.py index e42a480d9b..463d91336c 100644 --- a/satpy/readers/hdf5_utils.py +++ b/satpy/readers/hdf5_utils.py @@ -59,7 +59,11 @@ def __init__(self, filename, filename_info, filetype_info): def _collect_attrs(self, name, attrs): for key, value in six.iteritems(attrs): value = np.squeeze(value) - self.file_content["{}/attr/{}".format(name, key)] = np2str(value) + fc_key = "{}/attr/{}".format(name, key) + try: + self.file_content[fc_key] = np2str(value) + except ValueError: + self.file_content[fc_key] = value def collect_metadata(self, name, obj): if isinstance(obj, h5py.Dataset): diff --git a/satpy/readers/helper_functions.py b/satpy/readers/helper_functions.py index c3d978316f..9c0a2c54fe 100644 --- a/satpy/readers/helper_functions.py +++ b/satpy/readers/helper_functions.py @@ -33,14 +33,26 @@ def np2str(value): - """Convert an np.string_ to str.""" - if issubclass(value.dtype.type, np.string_): + """Convert an `numpy.string_` to str. + + Args: + value (ndarray): scalar or 1-element numpy array to convert + + Raises: + ValueError: if value is array larger than 1-element or it is not of + type np.string_ or it is not a numpy array + + """ + if hasattr(value, 'dtype') and \ + issubclass(value.dtype.type, np.string_) and value.size == 1: value = np.asscalar(value) if not isinstance(value, str): # python 3 - was scalar numpy array of bytes # otherwise python 2 - scalar numpy array of 'str' value = value.decode() - return value + return value + else: + raise ValueError("Array is not a string type or is larger than 1") def get_geostationary_angle_extent(geos_area): From 56f5b0067d7475bae52ee85aeb79bc68c9ef5c33 Mon Sep 17 00:00:00 2001 From: Panu Lahtinen Date: Fri, 2 Feb 2018 12:04:10 +0200 Subject: [PATCH 02/23] Add GenericCompositor --- satpy/composites/__init__.py | 45 ++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/satpy/composites/__init__.py b/satpy/composites/__init__.py index 0c9fb353dc..4d3a9780ba 100644 --- a/satpy/composites/__init__.py +++ b/satpy/composites/__init__.py @@ -547,6 +547,7 @@ def __call__(self, projectables, nonprojectables=None, **info): class RGBCompositor(CompositeBase): def __call__(self, projectables, nonprojectables=None, **info): + if len(projectables) != 3: raise ValueError("Expected 3 datasets, got %d" % (len(projectables), )) @@ -589,6 +590,7 @@ def __call__(self, projectables, nonprojectables=None, **info): class BWCompositor(CompositeBase): def __call__(self, projectables, nonprojectables=None, **info): + if len(projectables) != 1: raise ValueError("Expected 1 dataset, got %d" % (len(projectables), )) @@ -600,6 +602,49 @@ def __call__(self, projectables, nonprojectables=None, **info): return Dataset(projectables[0].copy(), **info.copy()) +class GenericCompositor(CompositeBase): + + modes = {1: 'L', 2: 'LA', 3: 'RGB', 4: 'RGBA'} + + def __call__(self, projectables, nonprojectables=None, **info): + + num = len(projectables) + mode = self.modes[num] + + try: + data = np.rollaxis(np.ma.dstack([projectable for projectable + in projectables]), axis=2) + except ValueError: + raise IncompatibleAreas + else: + areas = [projectable.info.get('area', None) + for projectable in projectables] + areas = [area for area in areas if area is not None] + if areas and areas.count(areas[0]) != len(areas): + raise IncompatibleAreas + + info = combine_info(*projectables) + info.update(self.info) + # FIXME: should this be done here ? + info["wavelength"] = None + info.pop("units", None) + sensor = set() + for projectable in projectables: + current_sensor = projectable.info.get("sensor", None) + if current_sensor: + if isinstance(current_sensor, (str, bytes, six.text_type)): + sensor.add(current_sensor) + else: + sensor |= current_sensor + if len(sensor) == 0: + sensor = None + elif len(sensor) == 1: + sensor = list(sensor)[0] + info["sensor"] = sensor + info["mode"] = mode + return Dataset(data=data, **info) + + class ColormapCompositor(RGBCompositor): """A compositor that uses colormaps.""" From 8be84c2d318ee2105ca428bce5b9ac51d0976260 Mon Sep 17 00:00:00 2001 From: Panu Lahtinen Date: Fri, 2 Feb 2018 12:04:32 +0200 Subject: [PATCH 03/23] Add depracition warnings to BWCompositor and RGBCompositor --- satpy/composites/__init__.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/satpy/composites/__init__.py b/satpy/composites/__init__.py index 4d3a9780ba..71040daa53 100644 --- a/satpy/composites/__init__.py +++ b/satpy/composites/__init__.py @@ -547,6 +547,7 @@ def __call__(self, projectables, nonprojectables=None, **info): class RGBCompositor(CompositeBase): def __call__(self, projectables, nonprojectables=None, **info): + "instead.", DeprecationWarning) if len(projectables) != 3: raise ValueError("Expected 3 datasets, got %d" % @@ -591,6 +592,10 @@ class BWCompositor(CompositeBase): def __call__(self, projectables, nonprojectables=None, **info): + import warnings + warnings.warn("RGBCompositor is deprecated, use GenericCompositor " + "instead.", DeprecationWarning) + if len(projectables) != 1: raise ValueError("Expected 1 dataset, got %d" % (len(projectables), )) From 43d207cb16dfd3d444be87fd507fca3bb14d590d Mon Sep 17 00:00:00 2001 From: Panu Lahtinen Date: Fri, 2 Feb 2018 12:09:47 +0200 Subject: [PATCH 04/23] Replace BWCompositor and RGBCompositor with GenericCompositor in YAML --- satpy/etc/composites/ahi.yaml | 22 +++++++++++----------- satpy/etc/composites/amsr2.yaml | 2 +- satpy/etc/composites/modis.yaml | 6 +++--- satpy/etc/composites/olci.yaml | 12 ++++++------ satpy/etc/composites/seviri.yaml | 16 ++++++++-------- satpy/etc/composites/slstr.yaml | 4 ++-- satpy/etc/composites/viirs.yaml | 28 ++++++++++++++-------------- satpy/etc/composites/visir.yaml | 20 ++++++++++---------- 8 files changed, 55 insertions(+), 55 deletions(-) diff --git a/satpy/etc/composites/ahi.yaml b/satpy/etc/composites/ahi.yaml index 28600f2dae..80086933d7 100644 --- a/satpy/etc/composites/ahi.yaml +++ b/satpy/etc/composites/ahi.yaml @@ -72,7 +72,7 @@ modifiers: composites: overview: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - 0.65 - 0.85 @@ -80,7 +80,7 @@ composites: standard_name: overview true_color: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - wavelength: 0.65 modifiers: [reducer2, effective_solar_pathlength_corrected, rayleigh_corrected] @@ -91,7 +91,7 @@ composites: standard_name: true_color true_color_reducedsize: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - wavelength: 0.65 modifiers: [reducer4, effective_solar_pathlength_corrected, @@ -105,7 +105,7 @@ composites: standard_name: true_color true_color_reducedsize_land: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - wavelength: 0.65 modifiers: [reducer4, effective_solar_pathlength_corrected, @@ -119,7 +119,7 @@ composites: standard_name: true_color true_color_reducedsize_marine_tropical: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - wavelength: 0.65 modifiers: [reducer4, effective_solar_pathlength_corrected, @@ -133,7 +133,7 @@ composites: standard_name: true_color true_color_norayleigh: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - wavelength: 0.65 modifiers: [reducer2, effective_solar_pathlength_corrected] @@ -144,7 +144,7 @@ composites: standard_name: true_color day_microphysics_eum: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - wavelength: 0.86 modifiers: [reducer4, ] @@ -155,7 +155,7 @@ composites: standard_name: day_microphysics day_microphysics_ahi: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - wavelength: 0.86 modifiers: [reducer4, ] @@ -166,7 +166,7 @@ composites: standard_name: day_microphysics cloud_phase_distinction: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - wavelength: 10.4 - wavelength: 0.64 @@ -175,7 +175,7 @@ composites: standard_name: cloud_phase_distinction water_vapors1: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - wavelength: 10.4 - wavelength: 6.2 @@ -190,7 +190,7 @@ composites: standard_name: mid_vapor water_vapors2: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: mid_vapor - wavelength: 7.3 diff --git a/satpy/etc/composites/amsr2.yaml b/satpy/etc/composites/amsr2.yaml index 344209bc77..f87265c483 100644 --- a/satpy/etc/composites/amsr2.yaml +++ b/satpy/etc/composites/amsr2.yaml @@ -2,7 +2,7 @@ sensor_name: amsr2 composites: rgb_color: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: 'btemp_10.7h' - name: 'btemp_36.5h' diff --git a/satpy/etc/composites/modis.yaml b/satpy/etc/composites/modis.yaml index fb5c436e87..e68a34e122 100644 --- a/satpy/etc/composites/modis.yaml +++ b/satpy/etc/composites/modis.yaml @@ -2,7 +2,7 @@ sensor_name: visir/modis composites: true_color_uncorrected: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: '1' modifiers: [sunz_corrected] @@ -13,7 +13,7 @@ composites: standard_name: true_color true_color: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: '1' modifiers: [sunz_corrected, rayleigh_corrected] @@ -24,7 +24,7 @@ composites: standard_name: true_color overview: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: '1' modifiers: [sunz_corrected] diff --git a/satpy/etc/composites/olci.yaml b/satpy/etc/composites/olci.yaml index 1ed5b5c7b2..559f4afb04 100644 --- a/satpy/etc/composites/olci.yaml +++ b/satpy/etc/composites/olci.yaml @@ -71,7 +71,7 @@ modifiers: composites: true_color: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: 'Oa08' modifiers: [effective_solar_pathlength_corrected, rayleigh_corrected] @@ -82,7 +82,7 @@ composites: standard_name: true_color true_color_land: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: 'Oa08' modifiers: [effective_solar_pathlength_corrected, rayleigh_corrected_land] @@ -93,7 +93,7 @@ composites: standard_name: true_color true_color_desert: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: 'Oa08' modifiers: [effective_solar_pathlength_corrected, rayleigh_corrected_desert] @@ -104,7 +104,7 @@ composites: standard_name: true_color true_color_marine_clean: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: 'Oa08' modifiers: [effective_solar_pathlength_corrected, rayleigh_corrected_marine_clean] @@ -115,7 +115,7 @@ composites: standard_name: true_color true_color_marine_tropical: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: 'Oa08' modifiers: [effective_solar_pathlength_corrected, rayleigh_corrected_marine_tropical] @@ -126,7 +126,7 @@ composites: standard_name: true_color true_color_raw: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: 'Oa08' modifiers: [effective_solar_pathlength_corrected] diff --git a/satpy/etc/composites/seviri.yaml b/satpy/etc/composites/seviri.yaml index cd47aa9840..f642af52e3 100644 --- a/satpy/etc/composites/seviri.yaml +++ b/satpy/etc/composites/seviri.yaml @@ -14,7 +14,7 @@ modifiers: composites: cloudtop: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - wavelength: 3.75 modifiers: [co2_corrected] @@ -23,7 +23,7 @@ composites: standard_name: cloudtop cloudtop_daytime: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - wavelength: 3.7 modifiers: [nir_emissive] @@ -53,7 +53,7 @@ composites: standard_name: night_fog snow: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: VIS008 modifiers: [sunz_corrected] @@ -64,7 +64,7 @@ composites: standard_name: snow day_microphysics: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: VIS008 modifiers: [sunz_corrected] @@ -74,7 +74,7 @@ composites: standard_name: day_microphysics day_microphysics_winter: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: VIS008 modifiers: [sunz_corrected] @@ -84,7 +84,7 @@ composites: standard_name: day_microphysics_winter natural: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - 1.63 - name: VIS008 @@ -92,7 +92,7 @@ composites: standard_name: natural natural_sun: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - wavelength: 1.63 modifiers: [sunz_corrected] @@ -247,7 +247,7 @@ composites: modifiers: [sunz_corrected] ir_overview: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - wavelength: 3.75 modifiers: [co2_corrected] diff --git a/satpy/etc/composites/slstr.yaml b/satpy/etc/composites/slstr.yaml index dcc8383cd6..f5c53bd0da 100644 --- a/satpy/etc/composites/slstr.yaml +++ b/satpy/etc/composites/slstr.yaml @@ -2,7 +2,7 @@ sensor_name: visir/slstr composites: overview: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - 0.65 - 0.86 @@ -10,7 +10,7 @@ composites: standard_name: overview day_microphysics: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - 0.86 - wavelength: 3.7 diff --git a/satpy/etc/composites/viirs.yaml b/satpy/etc/composites/viirs.yaml index 7b04dac66c..bec96baaf5 100644 --- a/satpy/etc/composites/viirs.yaml +++ b/satpy/etc/composites/viirs.yaml @@ -148,7 +148,7 @@ composites: high_resolution_band: red true_color_lowres: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: M05 modifiers: [sunz_corrected, rayleigh_corrected] @@ -159,7 +159,7 @@ composites: standard_name: true_color true_color_lowres_crefl: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: M05 modifiers: [sunz_corrected, rayleigh_corrected_crefl] @@ -170,7 +170,7 @@ composites: standard_name: true_color true_color_lowres_land: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: M05 modifiers: [sunz_corrected, rayleigh_corrected_land] @@ -181,7 +181,7 @@ composites: standard_name: true_color true_color_lowres_marine_tropical: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: M05 modifiers: [sunz_corrected, rayleigh_corrected_marine_tropical] @@ -207,7 +207,7 @@ composites: high_resolution_band: blue true_color_raw: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: M05 modifiers: [sunz_corrected] @@ -218,7 +218,7 @@ composites: standard_name: true_color night_overview: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - DNB - DNB @@ -226,7 +226,7 @@ composites: standard_name: night_overview overview: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - M05 - M07 @@ -234,7 +234,7 @@ composites: standard_name: overview hr_overview: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - I01 - I02 @@ -242,7 +242,7 @@ composites: standard_name: overview night_microphysics: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - hncc_dnb - M12 @@ -273,7 +273,7 @@ composites: standard_name: temperature_difference cloudtop_daytime: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: M12 modifiers: [nir_emissive_lowres] @@ -282,7 +282,7 @@ composites: standard_name: cloudtop hr_cloudtop_daytime: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: I04 modifiers: [nir_emissive_hires] @@ -291,7 +291,7 @@ composites: standard_name: cloudtop snow_lowres: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: M07 modifiers: [sunz_corrected] @@ -302,7 +302,7 @@ composites: standard_name: snow snow_hires: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: I02 modifiers: [sunz_corrected_iband] @@ -349,7 +349,7 @@ composites: units: "1" night_overview: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - hncc_dnb - hncc_dnb diff --git a/satpy/etc/composites/visir.yaml b/satpy/etc/composites/visir.yaml index da738dff86..f6495f53f4 100644 --- a/satpy/etc/composites/visir.yaml +++ b/satpy/etc/composites/visir.yaml @@ -116,7 +116,7 @@ composites: - 12.0 standard_name: ash cloudtop: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - 3.75 - 10.8 @@ -134,7 +134,7 @@ composites: standard_name: convection snow: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - wavelength: 0.8 modifiers: [sunz_corrected] @@ -145,7 +145,7 @@ composites: standard_name: snow day_microphysics: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - wavelength: 0.85 modifiers: [sunz_corrected] @@ -169,21 +169,21 @@ composites: - 12.0 standard_name: fog green_snow: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - 1.63 - 0.635 - 10.8 standard_name: green_snow natural: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - 1.63 - 0.85 - 0.635 standard_name: natural natural_sun: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - wavelength: 1.63 modifiers: [sunz_corrected] @@ -200,14 +200,14 @@ composites: - 12.0 standard_name: night_fog overview: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - 0.6 - 0.8 - 10.8 standard_name: overview overview_sun: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - wavelength: 0.6 modifiers: [sunz_corrected] @@ -217,7 +217,7 @@ composites: standard_name: overview true_color_raw: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - 0.65 - 0.5 @@ -297,7 +297,7 @@ composites: standard_name: night_microphysics ir108_3d: - compositor: !!python/name:satpy.composites.BWCompositor + compositor: !!python/name:satpy.composites.GenericCompositor standard_name: ir108_3d prerequisites: - name: IR_108 From 2c44edcd505f8aeeaed3807be23fee4db732a0be Mon Sep 17 00:00:00 2001 From: Panu Lahtinen Date: Fri, 2 Feb 2018 12:12:34 +0200 Subject: [PATCH 05/23] Replace RGBCompositor with GenericCompositor in abi.yaml --- satpy/etc/composites/abi.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/satpy/etc/composites/abi.yaml b/satpy/etc/composites/abi.yaml index 79d6ed219e..79394380d6 100644 --- a/satpy/etc/composites/abi.yaml +++ b/satpy/etc/composites/abi.yaml @@ -122,7 +122,7 @@ composites: standard_name: true_color overview: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - 0.65 - 0.85 From cba101d757e9b99cde837018fe9f1410ccb11a32 Mon Sep 17 00:00:00 2001 From: Panu Lahtinen Date: Fri, 2 Feb 2018 12:16:23 +0200 Subject: [PATCH 06/23] Use GenericCompositor instead of RGBCompositor --- satpy/composites/__init__.py | 53 +++++++++++++++++++----------------- satpy/composites/abi.py | 6 ++-- satpy/composites/sar.py | 4 +-- 3 files changed, 33 insertions(+), 30 deletions(-) diff --git a/satpy/composites/__init__.py b/satpy/composites/__init__.py index 71040daa53..be50dace30 100644 --- a/satpy/composites/__init__.py +++ b/satpy/composites/__init__.py @@ -650,7 +650,7 @@ def __call__(self, projectables, nonprojectables=None, **info): return Dataset(data=data, **info) -class ColormapCompositor(RGBCompositor): +class ColormapCompositor(GenericCompositor): """A compositor that uses colormaps.""" @staticmethod @@ -730,7 +730,7 @@ def __call__(self, projectables, **info): return super(PaletteCompositor, self).__call__((r, g, b), **data.info) -class DayNightCompositor(RGBCompositor): +class DayNightCompositor(GenericCompositor): """A compositor that takes one composite on the night side, another on day side, and then blends them together.""" @@ -778,10 +778,10 @@ def __call__(self, projectables, lim_low=85., lim_high=95., *args, **projectables[0].info) full_data.append(data) - res = RGBCompositor.__call__(self, (full_data[0], - full_data[1], - full_data[2]), - *args, **kwargs) + res = GenericCompositor.__call__(self, (full_data[0], + full_data[1], + full_data[2]), + *args, **kwargs) except ValueError: raise IncompatibleAreas @@ -789,7 +789,7 @@ def __call__(self, projectables, lim_low=85., lim_high=95., *args, return res -class Airmass(RGBCompositor): +class Airmass(GenericCompositor): def __call__(self, projectables, *args, **kwargs): """Make an airmass RGB image composite. @@ -805,16 +805,17 @@ def __call__(self, projectables, *args, **kwargs): +--------------------+--------------------+--------------------+ """ try: - res = RGBCompositor.__call__(self, (projectables[0] - projectables[1], - projectables[2] - - projectables[3], - projectables[0]), *args, **kwargs) + res = GenericCompositor.__call__(self, + (projectables[0] - projectables[1], + projectables[2] - + projectables[3], + projectables[0]), *args, **kwargs) except ValueError: raise IncompatibleAreas return res -class Convection(RGBCompositor): +class Convection(GenericCompositor): def __call__(self, projectables, *args, **kwargs): """Make a Severe Convection RGB image composite. @@ -830,17 +831,18 @@ def __call__(self, projectables, *args, **kwargs): +--------------------+--------------------+--------------------+ """ try: - res = RGBCompositor.__call__(self, (projectables[3] - projectables[4], - projectables[2] - - projectables[5], - projectables[1] - projectables[0]), - *args, **kwargs) + res = GenericCompositor.__call__(self, + (projectables[3] - projectables[4], + projectables[2] - + projectables[5], + projectables[1] - projectables[0]), + *args, **kwargs) except ValueError: raise IncompatibleAreas return res -class Dust(RGBCompositor): +class Dust(GenericCompositor): def __call__(self, projectables, *args, **kwargs): """Make a dust (or fog or night_fog) RGB image composite. @@ -868,17 +870,18 @@ def __call__(self, projectables, *args, **kwargs): +--------------------+--------------------+--------------------+ """ try: - res = RGBCompositor.__call__(self, (projectables[2] - projectables[1], - projectables[1] - - projectables[0], - projectables[1]), *args, **kwargs) + res = GenericCompositor.__call__(self, + (projectables[2] - projectables[1], + projectables[1] - + projectables[0], + projectables[1]), *args, **kwargs) except ValueError: raise IncompatibleAreas return res -class RealisticColors(RGBCompositor): +class RealisticColors(GenericCompositor): def __call__(self, projectables, *args, **kwargs): try: @@ -904,8 +907,8 @@ def __call__(self, projectables, *args, **kwargs): copy=False, **hrv.info) - res = RGBCompositor.__call__(self, (ch1, ch2, ch3), - *args, **kwargs) + res = GenericCompositor.__call__(self, (ch1, ch2, ch3), + *args, **kwargs) except ValueError: raise IncompatibleAreas return res diff --git a/satpy/composites/abi.py b/satpy/composites/abi.py index 50b523176e..926525efd0 100644 --- a/satpy/composites/abi.py +++ b/satpy/composites/abi.py @@ -25,7 +25,7 @@ import logging import numpy as np -from satpy.composites import RGBCompositor +from satpy.composites import GenericCompositor LOG = logging.getLogger(__name__) @@ -46,7 +46,7 @@ def simulated_green(c01, c02, c03): return (c01 + c02) / 2 * 0.93 + 0.07 * c03 -class TrueColor2km(RGBCompositor): +class TrueColor2km(GenericCompositor): """True Color ABI compositor assuming all bands are the same resolution""" def __call__(self, projectables, **info): @@ -60,7 +60,7 @@ def __call__(self, projectables, **info): return super(TrueColor2km, self).__call__((r, g, b), **info) -class TrueColor(RGBCompositor): +class TrueColor(GenericCompositor): """Ratio sharpened full resolution true color""" def __call__(self, projectables, **info): diff --git a/satpy/composites/sar.py b/satpy/composites/sar.py index 1f93007239..8dd28b3709 100644 --- a/satpy/composites/sar.py +++ b/satpy/composites/sar.py @@ -24,7 +24,7 @@ import logging -from satpy.composites import RGBCompositor +from satpy.composites import GenericCompositor from satpy.dataset import combine_info LOG = logging.getLogger(__name__) @@ -48,7 +48,7 @@ def overlay(top, bottom): return res -class SARIce(RGBCompositor): +class SARIce(GenericCompositor): """The SAR Ice composite.""" def __call__(self, projectables, *args, **kwargs): From 475cfc6f3ffd38491b8463ed8c500f07867b4192 Mon Sep 17 00:00:00 2001 From: Panu Lahtinen Date: Fri, 2 Feb 2018 12:18:32 +0200 Subject: [PATCH 07/23] Use GenericCompositor in documentation --- doc/source/composites.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/source/composites.rst b/doc/source/composites.rst index ecf5a0b4de..576905335a 100644 --- a/doc/source/composites.rst +++ b/doc/source/composites.rst @@ -14,11 +14,11 @@ Making custom composites These features will be added to the ``Scene`` object in the future. -Building custom composites makes use of the :class:`RGBCompositor` class. For example, +Building custom composites makes use of the :class:`GenericCompositor` class. For example, building an overview composite can be done manually with:: - >>> from satpy.composites import RGBCompositor - >>> compositor = RGBCompositor("myoverview", "bla", "") + >>> from satpy.composites import GenericCompositor + >>> compositor = GenericCompositor("myoverview", "bla", "") >>> composite = compositor([local_scene[0.6], ... local_scene[0.8], ... local_scene[10.8]]) From d888da6cd36c9220faae9d9e8e1d251280416b48 Mon Sep 17 00:00:00 2001 From: Panu Lahtinen Date: Fri, 2 Feb 2018 12:29:56 +0200 Subject: [PATCH 08/23] Add two missing deprecation warning lines --- satpy/composites/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/satpy/composites/__init__.py b/satpy/composites/__init__.py index be50dace30..7c6a880afd 100644 --- a/satpy/composites/__init__.py +++ b/satpy/composites/__init__.py @@ -547,6 +547,9 @@ def __call__(self, projectables, nonprojectables=None, **info): class RGBCompositor(CompositeBase): def __call__(self, projectables, nonprojectables=None, **info): + + import warnings + warnings.warn("RGBCompositor is deprecated, use GenericCompositor " "instead.", DeprecationWarning) if len(projectables) != 3: From fda0be068d53ff31e5fd1764b544dea31931be3a Mon Sep 17 00:00:00 2001 From: Panu Lahtinen Date: Fri, 2 Feb 2018 12:04:10 +0200 Subject: [PATCH 09/23] Add GenericCompositor --- satpy/composites/__init__.py | 45 ++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/satpy/composites/__init__.py b/satpy/composites/__init__.py index d81ef435c4..1751feb26e 100644 --- a/satpy/composites/__init__.py +++ b/satpy/composites/__init__.py @@ -560,6 +560,7 @@ def __call__(self, projectables, nonprojectables=None, **info): class RGBCompositor(CompositeBase): def __call__(self, projectables, nonprojectables=None, **info): + if len(projectables) != 3: raise ValueError("Expected 3 datasets, got %d" % (len(projectables), )) @@ -621,6 +622,7 @@ def __call__(self, projectables, nonprojectables=None, **info): class BWCompositor(CompositeBase): def __call__(self, projectables, nonprojectables=None, **info): + if len(projectables) != 1: raise ValueError("Expected 1 dataset, got %d" % (len(projectables), )) @@ -632,6 +634,49 @@ def __call__(self, projectables, nonprojectables=None, **info): return Dataset(projectables[0].copy(), **info.copy()) +class GenericCompositor(CompositeBase): + + modes = {1: 'L', 2: 'LA', 3: 'RGB', 4: 'RGBA'} + + def __call__(self, projectables, nonprojectables=None, **info): + + num = len(projectables) + mode = self.modes[num] + + try: + data = np.rollaxis(np.ma.dstack([projectable for projectable + in projectables]), axis=2) + except ValueError: + raise IncompatibleAreas + else: + areas = [projectable.info.get('area', None) + for projectable in projectables] + areas = [area for area in areas if area is not None] + if areas and areas.count(areas[0]) != len(areas): + raise IncompatibleAreas + + info = combine_info(*projectables) + info.update(self.info) + # FIXME: should this be done here ? + info["wavelength"] = None + info.pop("units", None) + sensor = set() + for projectable in projectables: + current_sensor = projectable.info.get("sensor", None) + if current_sensor: + if isinstance(current_sensor, (str, bytes, six.text_type)): + sensor.add(current_sensor) + else: + sensor |= current_sensor + if len(sensor) == 0: + sensor = None + elif len(sensor) == 1: + sensor = list(sensor)[0] + info["sensor"] = sensor + info["mode"] = mode + return Dataset(data=data, **info) + + class ColormapCompositor(RGBCompositor): """A compositor that uses colormaps.""" From ac59500ae43a4e97258c14a5c2ea356c1382b6bf Mon Sep 17 00:00:00 2001 From: Panu Lahtinen Date: Fri, 2 Feb 2018 12:04:32 +0200 Subject: [PATCH 10/23] Add depracition warnings to BWCompositor and RGBCompositor --- satpy/composites/__init__.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/satpy/composites/__init__.py b/satpy/composites/__init__.py index 1751feb26e..0f30ef0916 100644 --- a/satpy/composites/__init__.py +++ b/satpy/composites/__init__.py @@ -560,6 +560,7 @@ def __call__(self, projectables, nonprojectables=None, **info): class RGBCompositor(CompositeBase): def __call__(self, projectables, nonprojectables=None, **info): + "instead.", DeprecationWarning) if len(projectables) != 3: raise ValueError("Expected 3 datasets, got %d" % @@ -623,6 +624,10 @@ class BWCompositor(CompositeBase): def __call__(self, projectables, nonprojectables=None, **info): + import warnings + warnings.warn("RGBCompositor is deprecated, use GenericCompositor " + "instead.", DeprecationWarning) + if len(projectables) != 1: raise ValueError("Expected 1 dataset, got %d" % (len(projectables), )) From 8dc13a00ebb4eef1abdf644c8b96e92e1ee71dfc Mon Sep 17 00:00:00 2001 From: Panu Lahtinen Date: Fri, 2 Feb 2018 12:09:47 +0200 Subject: [PATCH 11/23] Replace BWCompositor and RGBCompositor with GenericCompositor in YAML --- satpy/etc/composites/ahi.yaml | 22 +++++++++++----------- satpy/etc/composites/amsr2.yaml | 2 +- satpy/etc/composites/modis.yaml | 6 +++--- satpy/etc/composites/olci.yaml | 12 ++++++------ satpy/etc/composites/seviri.yaml | 16 ++++++++-------- satpy/etc/composites/slstr.yaml | 4 ++-- satpy/etc/composites/viirs.yaml | 28 ++++++++++++++-------------- satpy/etc/composites/visir.yaml | 20 ++++++++++---------- 8 files changed, 55 insertions(+), 55 deletions(-) diff --git a/satpy/etc/composites/ahi.yaml b/satpy/etc/composites/ahi.yaml index 28600f2dae..80086933d7 100644 --- a/satpy/etc/composites/ahi.yaml +++ b/satpy/etc/composites/ahi.yaml @@ -72,7 +72,7 @@ modifiers: composites: overview: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - 0.65 - 0.85 @@ -80,7 +80,7 @@ composites: standard_name: overview true_color: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - wavelength: 0.65 modifiers: [reducer2, effective_solar_pathlength_corrected, rayleigh_corrected] @@ -91,7 +91,7 @@ composites: standard_name: true_color true_color_reducedsize: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - wavelength: 0.65 modifiers: [reducer4, effective_solar_pathlength_corrected, @@ -105,7 +105,7 @@ composites: standard_name: true_color true_color_reducedsize_land: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - wavelength: 0.65 modifiers: [reducer4, effective_solar_pathlength_corrected, @@ -119,7 +119,7 @@ composites: standard_name: true_color true_color_reducedsize_marine_tropical: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - wavelength: 0.65 modifiers: [reducer4, effective_solar_pathlength_corrected, @@ -133,7 +133,7 @@ composites: standard_name: true_color true_color_norayleigh: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - wavelength: 0.65 modifiers: [reducer2, effective_solar_pathlength_corrected] @@ -144,7 +144,7 @@ composites: standard_name: true_color day_microphysics_eum: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - wavelength: 0.86 modifiers: [reducer4, ] @@ -155,7 +155,7 @@ composites: standard_name: day_microphysics day_microphysics_ahi: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - wavelength: 0.86 modifiers: [reducer4, ] @@ -166,7 +166,7 @@ composites: standard_name: day_microphysics cloud_phase_distinction: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - wavelength: 10.4 - wavelength: 0.64 @@ -175,7 +175,7 @@ composites: standard_name: cloud_phase_distinction water_vapors1: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - wavelength: 10.4 - wavelength: 6.2 @@ -190,7 +190,7 @@ composites: standard_name: mid_vapor water_vapors2: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: mid_vapor - wavelength: 7.3 diff --git a/satpy/etc/composites/amsr2.yaml b/satpy/etc/composites/amsr2.yaml index 344209bc77..f87265c483 100644 --- a/satpy/etc/composites/amsr2.yaml +++ b/satpy/etc/composites/amsr2.yaml @@ -2,7 +2,7 @@ sensor_name: amsr2 composites: rgb_color: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: 'btemp_10.7h' - name: 'btemp_36.5h' diff --git a/satpy/etc/composites/modis.yaml b/satpy/etc/composites/modis.yaml index fb5c436e87..e68a34e122 100644 --- a/satpy/etc/composites/modis.yaml +++ b/satpy/etc/composites/modis.yaml @@ -2,7 +2,7 @@ sensor_name: visir/modis composites: true_color_uncorrected: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: '1' modifiers: [sunz_corrected] @@ -13,7 +13,7 @@ composites: standard_name: true_color true_color: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: '1' modifiers: [sunz_corrected, rayleigh_corrected] @@ -24,7 +24,7 @@ composites: standard_name: true_color overview: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: '1' modifiers: [sunz_corrected] diff --git a/satpy/etc/composites/olci.yaml b/satpy/etc/composites/olci.yaml index 1ed5b5c7b2..559f4afb04 100644 --- a/satpy/etc/composites/olci.yaml +++ b/satpy/etc/composites/olci.yaml @@ -71,7 +71,7 @@ modifiers: composites: true_color: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: 'Oa08' modifiers: [effective_solar_pathlength_corrected, rayleigh_corrected] @@ -82,7 +82,7 @@ composites: standard_name: true_color true_color_land: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: 'Oa08' modifiers: [effective_solar_pathlength_corrected, rayleigh_corrected_land] @@ -93,7 +93,7 @@ composites: standard_name: true_color true_color_desert: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: 'Oa08' modifiers: [effective_solar_pathlength_corrected, rayleigh_corrected_desert] @@ -104,7 +104,7 @@ composites: standard_name: true_color true_color_marine_clean: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: 'Oa08' modifiers: [effective_solar_pathlength_corrected, rayleigh_corrected_marine_clean] @@ -115,7 +115,7 @@ composites: standard_name: true_color true_color_marine_tropical: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: 'Oa08' modifiers: [effective_solar_pathlength_corrected, rayleigh_corrected_marine_tropical] @@ -126,7 +126,7 @@ composites: standard_name: true_color true_color_raw: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: 'Oa08' modifiers: [effective_solar_pathlength_corrected] diff --git a/satpy/etc/composites/seviri.yaml b/satpy/etc/composites/seviri.yaml index 678d1d85dd..1309c23856 100644 --- a/satpy/etc/composites/seviri.yaml +++ b/satpy/etc/composites/seviri.yaml @@ -14,7 +14,7 @@ modifiers: composites: cloudtop: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - wavelength: 3.75 modifiers: [co2_corrected] @@ -23,7 +23,7 @@ composites: standard_name: cloudtop cloudtop_daytime: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - wavelength: 3.7 modifiers: [nir_emissive] @@ -53,7 +53,7 @@ composites: standard_name: night_fog snow: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: VIS008 modifiers: [sunz_corrected] @@ -64,7 +64,7 @@ composites: standard_name: snow day_microphysics: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: VIS008 modifiers: [sunz_corrected] @@ -74,7 +74,7 @@ composites: standard_name: day_microphysics day_microphysics_winter: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: VIS008 modifiers: [sunz_corrected] @@ -84,7 +84,7 @@ composites: standard_name: day_microphysics_winter natural: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - 1.63 - name: VIS008 @@ -92,7 +92,7 @@ composites: standard_name: natural natural_sun: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - wavelength: 1.63 modifiers: [sunz_corrected] @@ -247,7 +247,7 @@ composites: modifiers: [sunz_corrected] ir_overview: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - wavelength: 3.75 modifiers: [co2_corrected] diff --git a/satpy/etc/composites/slstr.yaml b/satpy/etc/composites/slstr.yaml index dcc8383cd6..f5c53bd0da 100644 --- a/satpy/etc/composites/slstr.yaml +++ b/satpy/etc/composites/slstr.yaml @@ -2,7 +2,7 @@ sensor_name: visir/slstr composites: overview: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - 0.65 - 0.86 @@ -10,7 +10,7 @@ composites: standard_name: overview day_microphysics: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - 0.86 - wavelength: 3.7 diff --git a/satpy/etc/composites/viirs.yaml b/satpy/etc/composites/viirs.yaml index 89a172fd99..6c117558ac 100644 --- a/satpy/etc/composites/viirs.yaml +++ b/satpy/etc/composites/viirs.yaml @@ -148,7 +148,7 @@ composites: high_resolution_band: red true_color_lowres: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: M05 modifiers: [sunz_corrected, rayleigh_corrected] @@ -159,7 +159,7 @@ composites: standard_name: true_color true_color_lowres_crefl: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: M05 modifiers: [sunz_corrected, rayleigh_corrected_crefl] @@ -170,7 +170,7 @@ composites: standard_name: true_color true_color_lowres_land: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: M05 modifiers: [sunz_corrected, rayleigh_corrected_land] @@ -181,7 +181,7 @@ composites: standard_name: true_color true_color_lowres_marine_tropical: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: M05 modifiers: [sunz_corrected, rayleigh_corrected_marine_tropical] @@ -229,7 +229,7 @@ composites: standard_name: natural true_color_raw: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: M05 modifiers: [sunz_corrected] @@ -240,7 +240,7 @@ composites: standard_name: true_color night_overview: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - DNB - DNB @@ -248,7 +248,7 @@ composites: standard_name: night_overview overview: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - M05 - M07 @@ -256,7 +256,7 @@ composites: standard_name: overview hr_overview: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - I01 - I02 @@ -264,7 +264,7 @@ composites: standard_name: overview night_microphysics: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - hncc_dnb - M12 @@ -311,7 +311,7 @@ composites: standard_name: temperature_difference cloudtop_daytime: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: M12 modifiers: [nir_emissive_lowres] @@ -320,7 +320,7 @@ composites: standard_name: cloudtop hr_cloudtop_daytime: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: I04 modifiers: [nir_emissive_hires] @@ -329,7 +329,7 @@ composites: standard_name: cloudtop snow_lowres: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: M07 modifiers: [sunz_corrected] @@ -340,7 +340,7 @@ composites: standard_name: snow snow_hires: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - name: I02 modifiers: [sunz_corrected_iband] @@ -387,7 +387,7 @@ composites: units: "1" night_overview: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - hncc_dnb - hncc_dnb diff --git a/satpy/etc/composites/visir.yaml b/satpy/etc/composites/visir.yaml index b1b719ac50..bfbf6dcf45 100644 --- a/satpy/etc/composites/visir.yaml +++ b/satpy/etc/composites/visir.yaml @@ -118,7 +118,7 @@ composites: - 12.0 standard_name: ash cloudtop: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - 3.75 - 10.8 @@ -136,7 +136,7 @@ composites: standard_name: convection snow: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - wavelength: 0.8 modifiers: [sunz_corrected] @@ -147,7 +147,7 @@ composites: standard_name: snow day_microphysics: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - wavelength: 0.85 modifiers: [sunz_corrected] @@ -171,21 +171,21 @@ composites: - 12.0 standard_name: fog green_snow: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - 1.63 - 0.635 - 10.8 standard_name: green_snow natural: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - 1.63 - 0.85 - 0.635 standard_name: natural natural_sun: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - wavelength: 1.63 modifiers: [sunz_corrected] @@ -202,14 +202,14 @@ composites: - 12.0 standard_name: night_fog overview: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - 0.6 - 0.8 - 10.8 standard_name: overview overview_sun: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - wavelength: 0.6 modifiers: [sunz_corrected] @@ -219,7 +219,7 @@ composites: standard_name: overview true_color_raw: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - 0.65 - 0.5 @@ -299,7 +299,7 @@ composites: standard_name: night_microphysics ir108_3d: - compositor: !!python/name:satpy.composites.BWCompositor + compositor: !!python/name:satpy.composites.GenericCompositor standard_name: ir108_3d prerequisites: - name: IR_108 From 58e3bd86ea53680bf1ba02d443d2bbae6bcfbf7d Mon Sep 17 00:00:00 2001 From: Panu Lahtinen Date: Fri, 2 Feb 2018 12:12:34 +0200 Subject: [PATCH 12/23] Replace RGBCompositor with GenericCompositor in abi.yaml --- satpy/etc/composites/abi.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/satpy/etc/composites/abi.yaml b/satpy/etc/composites/abi.yaml index 189b90accd..96458e4bf3 100644 --- a/satpy/etc/composites/abi.yaml +++ b/satpy/etc/composites/abi.yaml @@ -122,7 +122,7 @@ composites: standard_name: true_color overview: - compositor: !!python/name:satpy.composites.RGBCompositor + compositor: !!python/name:satpy.composites.GenericCompositor prerequisites: - 0.65 - 0.85 From be4bb039400dfb57501e0d8494fa7cc01b8923cb Mon Sep 17 00:00:00 2001 From: Panu Lahtinen Date: Fri, 2 Feb 2018 12:16:23 +0200 Subject: [PATCH 13/23] Use GenericCompositor instead of RGBCompositor --- satpy/composites/__init__.py | 42 +++++++++++++++++++----------------- satpy/composites/abi.py | 6 +++--- satpy/composites/sar.py | 4 ++-- 3 files changed, 27 insertions(+), 25 deletions(-) diff --git a/satpy/composites/__init__.py b/satpy/composites/__init__.py index 0f30ef0916..01523bd45c 100644 --- a/satpy/composites/__init__.py +++ b/satpy/composites/__init__.py @@ -1,12 +1,13 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -# Copyright (c) 2015-2018 +# Copyright (c) 2015-2018 PyTroll developers # Author(s): # Martin Raspaud # David Hoese +# Adam Dybbroe # 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 @@ -682,7 +683,7 @@ def __call__(self, projectables, nonprojectables=None, **info): return Dataset(data=data, **info) -class ColormapCompositor(RGBCompositor): +class ColormapCompositor(GenericCompositor): """A compositor that uses colormaps.""" @staticmethod @@ -768,7 +769,7 @@ def __call__(self, projectables, **info): return super(PaletteCompositor, self).__call__((r, g, b), **data.attrs) -class DayNightCompositor(RGBCompositor): +class DayNightCompositor(GenericCompositor): """A compositor that takes one composite on the night side, another on day side, and then blends them together.""" @@ -816,10 +817,10 @@ def __call__(self, projectables, lim_low=85., lim_high=95., *args, **projectables[0].info) full_data.append(data) - res = RGBCompositor.__call__(self, (full_data[0], - full_data[1], - full_data[2]), - *args, **kwargs) + res = GenericCompositor.__call__(self, (full_data[0], + full_data[1], + full_data[2]), + *args, **kwargs) except ValueError: raise IncompatibleAreas @@ -838,7 +839,7 @@ def sub_arrays(proj1, proj2): return res -class Airmass(RGBCompositor): +class Airmass(GenericCompositor): def __call__(self, projectables, *args, **kwargs): """Make an airmass RGB image composite. @@ -856,7 +857,7 @@ def __call__(self, projectables, *args, **kwargs): try: ch1 = sub_arrays(projectables[0], projectables[1]) ch2 = sub_arrays(projectables[2], projectables[3]) - res = RGBCompositor.__call__(self, (ch1, ch2, + res = GenericCompositor.__call__(self, (ch1, ch2, projectables[0]), *args, **kwargs) except ValueError: @@ -864,7 +865,7 @@ def __call__(self, projectables, *args, **kwargs): return res -class Convection(RGBCompositor): +class Convection(GenericCompositor): def __call__(self, projectables, *args, **kwargs): """Make a Severe Convection RGB image composite. @@ -880,17 +881,18 @@ def __call__(self, projectables, *args, **kwargs): +--------------------+--------------------+--------------------+ """ try: - res = RGBCompositor.__call__(self, (projectables[3] - projectables[4], - projectables[2] - - projectables[5], - projectables[1] - projectables[0]), - *args, **kwargs) + res = GenericCompositor.__call__(self, + (projectables[3] - projectables[4], + projectables[2] - + projectables[5], + projectables[1] - projectables[0]), + *args, **kwargs) except ValueError: raise IncompatibleAreas return res -class Dust(RGBCompositor): +class Dust(GenericCompositor): def __call__(self, projectables, *args, **kwargs): """Make a dust (or fog or night_fog) RGB image composite. @@ -921,7 +923,7 @@ def __call__(self, projectables, *args, **kwargs): ch1 = sub_arrays(projectables[2], projectables[1]) ch2 = sub_arrays(projectables[1], projectables[0]) - res = RGBCompositor.__call__(self, (ch1, ch2, + res = GenericCompositor.__call__(self, (ch1, ch2, projectables[1]), *args, **kwargs) except ValueError: raise IncompatibleAreas @@ -929,7 +931,7 @@ def __call__(self, projectables, *args, **kwargs): return res -class RealisticColors(RGBCompositor): +class RealisticColors(GenericCompositor): def __call__(self, projectables, *args, **kwargs): try: @@ -952,8 +954,8 @@ def __call__(self, projectables, *args, **kwargs): ch2 = ndvi * vis08 + (1 - ndvi) * vis06 ch2.attrs = vis08.attrs - res = RGBCompositor.__call__(self, (ch1, ch2, ch3), - *args, **kwargs) + res = GenericCompositor.__call__(self, (ch1, ch2, ch3), + *args, **kwargs) except ValueError: raise IncompatibleAreas return res diff --git a/satpy/composites/abi.py b/satpy/composites/abi.py index 4c3acccd2b..5c484252bb 100644 --- a/satpy/composites/abi.py +++ b/satpy/composites/abi.py @@ -25,7 +25,7 @@ import logging import numpy as np -from satpy.composites import RGBCompositor +from satpy.composites import GenericCompositor LOG = logging.getLogger(__name__) @@ -46,7 +46,7 @@ def simulated_green(c01, c02, c03): return (c01 + c02) / 2 * 0.93 + 0.07 * c03 -class TrueColor2km(RGBCompositor): +class TrueColor2km(GenericCompositor): """True Color ABI compositor assuming all bands are the same resolution""" def __call__(self, projectables, **info): @@ -70,7 +70,7 @@ def __call__(self, projectables, **info): return super(TrueColor2km, self).__call__((r, g, b), **info) -class TrueColor(RGBCompositor): +class TrueColor(GenericCompositor): """Ratio sharpened full resolution true color""" def __call__(self, projectables, **info): diff --git a/satpy/composites/sar.py b/satpy/composites/sar.py index 1eebd4a8db..7fc44de723 100644 --- a/satpy/composites/sar.py +++ b/satpy/composites/sar.py @@ -24,7 +24,7 @@ import logging -from satpy.composites import RGBCompositor +from satpy.composites import GenericCompositor from satpy.dataset import combine_metadata LOG = logging.getLogger(__name__) @@ -48,7 +48,7 @@ def overlay(top, bottom): return res -class SARIce(RGBCompositor): +class SARIce(GenericCompositor): """The SAR Ice composite.""" def __call__(self, projectables, *args, **kwargs): From 34b0fb0fa0bbb7cfa3477cbc634c56fac6fb201c Mon Sep 17 00:00:00 2001 From: Panu Lahtinen Date: Fri, 2 Feb 2018 12:18:32 +0200 Subject: [PATCH 14/23] Use GenericCompositor in documentation --- doc/source/composites.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/source/composites.rst b/doc/source/composites.rst index ecf5a0b4de..576905335a 100644 --- a/doc/source/composites.rst +++ b/doc/source/composites.rst @@ -14,11 +14,11 @@ Making custom composites These features will be added to the ``Scene`` object in the future. -Building custom composites makes use of the :class:`RGBCompositor` class. For example, +Building custom composites makes use of the :class:`GenericCompositor` class. For example, building an overview composite can be done manually with:: - >>> from satpy.composites import RGBCompositor - >>> compositor = RGBCompositor("myoverview", "bla", "") + >>> from satpy.composites import GenericCompositor + >>> compositor = GenericCompositor("myoverview", "bla", "") >>> composite = compositor([local_scene[0.6], ... local_scene[0.8], ... local_scene[10.8]]) From ecbe6fa51bdbb1904b2ae264d26f3f87b6e8835c Mon Sep 17 00:00:00 2001 From: Panu Lahtinen Date: Fri, 2 Feb 2018 12:29:56 +0200 Subject: [PATCH 15/23] Add two missing deprecation warning lines --- satpy/composites/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/satpy/composites/__init__.py b/satpy/composites/__init__.py index 01523bd45c..6f5b77d5a5 100644 --- a/satpy/composites/__init__.py +++ b/satpy/composites/__init__.py @@ -561,6 +561,9 @@ def __call__(self, projectables, nonprojectables=None, **info): class RGBCompositor(CompositeBase): def __call__(self, projectables, nonprojectables=None, **info): + + import warnings + warnings.warn("RGBCompositor is deprecated, use GenericCompositor " "instead.", DeprecationWarning) if len(projectables) != 3: From 9577b2291bad4e96b2030e5bc843f14e0a29af41 Mon Sep 17 00:00:00 2001 From: howff Date: Tue, 6 Feb 2018 14:33:35 +0000 Subject: [PATCH 16/23] Update abi_l1b.yaml to allow C01 filename C01 filename from Eumetcast has -{chid:6d}_0 suffix just like C02 --- satpy/etc/readers/abi_l1b.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/satpy/etc/readers/abi_l1b.yaml b/satpy/etc/readers/abi_l1b.yaml index 6ca9c52d33..8c3c023503 100644 --- a/satpy/etc/readers/abi_l1b.yaml +++ b/satpy/etc/readers/abi_l1b.yaml @@ -8,7 +8,8 @@ reader: file_types: c01: file_reader: !!python/name:satpy.readers.abi_l1b.NC_ABI_L1B - file_patterns: ['{system_environment:2s}_{mission_id:3s}-L1b-{dataset_name:3s}{area_code:s}-{scan_mode:2s}C01_{platform_shortname:3s}_s{start_time:%Y%j%H%M%S%f}_e{end_time:%Y%j%H%M%S%f}_c{creation_time:%Y%j%H%M%S%f}.nc'] + file_patterns: ['{system_environment:2s}_{mission_id:3s}-L1b-{dataset_name:3s}{area_code:s}-{scan_mode:2s}C01_{platform_shortname:3s}_s{start_time:%Y%j%H%M%S%f}_e{end_time:%Y%j%H%M%S%f}_c{creation_time:%Y%j%H%M%S%f}.nc', + '{system_environment:2s}_{mission_id:3s}-L1b-{dataset_name:3s}{area_code:s}-{scan_mode:2s}C01_{platform_shortname:3s}_s{start_time:%Y%j%H%M%S%f}_e{end_time:%Y%j%H%M%S%f}_c{creation_time:%Y%j%H%M%S%f}-{chid:6d}_0.nc'] c02: file_reader: !!python/name:satpy.readers.abi_l1b.NC_ABI_L1B file_patterns: ['{system_environment:2s}_{mission_id:3s}-L1b-{dataset_name:3s}{area_code:s}-{scan_mode:2s}C02_{platform_shortname:3s}_s{start_time:%Y%j%H%M%S%f}_e{end_time:%Y%j%H%M%S%f}_c{creation_time:%Y%j%H%M%S%f}.nc', From 5be0b0a9a9c41d750976bbff53865f603f4b998f Mon Sep 17 00:00:00 2001 From: Martin Raspaud Date: Wed, 7 Feb 2018 10:56:55 +0100 Subject: [PATCH 17/23] Fix the nc_nwcsaf_pps reader config for file finding compatibility --- satpy/etc/readers/nc_nwcsaf_pps.yaml | 2 +- satpy/tests/test_readers.py | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/satpy/etc/readers/nc_nwcsaf_pps.yaml b/satpy/etc/readers/nc_nwcsaf_pps.yaml index a34fe054d3..ce2e509bb4 100644 --- a/satpy/etc/readers/nc_nwcsaf_pps.yaml +++ b/satpy/etc/readers/nc_nwcsaf_pps.yaml @@ -1,6 +1,6 @@ reader: description: NetCDF4 reader for the NWCSAF/PPS 2014 format - name: nc_nwcsaf + name: nc_nwcsaf_pps sensors: ['avhrr-3', 'viirs', 'modis'] default_channels: [] reader: !!python/name:satpy.readers.yaml_reader.FileYAMLReader diff --git a/satpy/tests/test_readers.py b/satpy/tests/test_readers.py index f41bec47ae..6dfad82a93 100644 --- a/satpy/tests/test_readers.py +++ b/satpy/tests/test_readers.py @@ -192,6 +192,20 @@ def test_reader_name(self): finally: os.remove(fn) + + def test_reader_other_name(self): + """Test with default base_dir and reader specified""" + from satpy.readers import find_files_and_readers + fn = 'S_NWC_CPP_npp_32505_20180204T1114116Z_20180204T1128227Z.nc' + # touch the file so it exists on disk + open(fn, 'w') + try: + ri = find_files_and_readers(reader='nc_nwcsaf_pps') + self.assertListEqual(list(ri.keys()), ['nc_nwcsaf_pps']) + self.assertListEqual(ri['nc_nwcsaf_pps'], [fn]) + finally: + os.remove(fn) + def test_reader_name_matched_start_end_time(self): """Test with start and end time matching the filename""" from satpy.readers import find_files_and_readers From e52f15cd3ec78370e8776ed151ea47ea7b58fad3 Mon Sep 17 00:00:00 2001 From: Martin Raspaud Date: Wed, 7 Feb 2018 11:01:22 +0100 Subject: [PATCH 18/23] Make flake8 happy --- satpy/tests/test_readers.py | 1 - 1 file changed, 1 deletion(-) diff --git a/satpy/tests/test_readers.py b/satpy/tests/test_readers.py index 6dfad82a93..1371e53fe2 100644 --- a/satpy/tests/test_readers.py +++ b/satpy/tests/test_readers.py @@ -192,7 +192,6 @@ def test_reader_name(self): finally: os.remove(fn) - def test_reader_other_name(self): """Test with default base_dir and reader specified""" from satpy.readers import find_files_and_readers From 1ca18e151ca927dab4071141fa83cfb08a1c9459 Mon Sep 17 00:00:00 2001 From: Merrit Mammani Date: Thu, 8 Feb 2018 15:40:37 +0000 Subject: [PATCH 19/23] Add missing nodata tiff tag --- satpy/writers/geotiff.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/satpy/writers/geotiff.py b/satpy/writers/geotiff.py index 089ff0e2e4..4fec8476d4 100644 --- a/satpy/writers/geotiff.py +++ b/satpy/writers/geotiff.py @@ -100,8 +100,10 @@ def _gdal_write_datasets(self, dst_ds, datasets, opacity, fill_value): """ if fill_value is not None: for i, chan in enumerate(datasets): - ds = chan.filled(fill_value[i]) - dst_ds.GetRasterBand(i + 1).WriteArray(ds) + chn = chan.filled(fill_value[i]) + bnd = dst_ds.GetRasterBand(i + 1) + bnd.SetNoDataValue(fill_value[i]) + bnd.WriteArray(chn) else: mask = np.zeros(datasets[0].shape, dtype=np.bool) i = 0 From d41a213afb2c3fcad24872da1bb57137e0f702a5 Mon Sep 17 00:00:00 2001 From: davidh-ssec Date: Fri, 9 Feb 2018 20:55:36 -0600 Subject: [PATCH 20/23] Update GenericCompositor to be compatible with xarray --- satpy/composites/__init__.py | 149 ++++++++++++++++++++--------------- 1 file changed, 84 insertions(+), 65 deletions(-) diff --git a/satpy/composites/__init__.py b/satpy/composites/__init__.py index 6f5b77d5a5..9b774a6a6f 100644 --- a/satpy/composites/__init__.py +++ b/satpy/composites/__init__.py @@ -329,18 +329,6 @@ def _apply_correction(self, proj, coszen): return atmospheric_path_length_correction(proj, coszen) -def show(data, filename=None): - """Show the stretched data. - """ - from PIL import Image as pil - img = pil.fromarray(((data - data.min()) * 255.0 / - (data.max() - data.min())).astype(np.uint8)) - if filename is None: - img.show() - else: - img.save(filename) - - class PSPRayleighReflectance(CompositeBase): def __call__(self, projectables, optional_datasets=None, **info): @@ -558,7 +546,7 @@ def __call__(self, projectables, nonprojectables=None, **info): return Dataset(projectables[0] - projectables[1], **info) -class RGBCompositor(CompositeBase): +class RGBCompositor(GenericCompositor): def __call__(self, projectables, nonprojectables=None, **info): @@ -569,6 +557,7 @@ def __call__(self, projectables, nonprojectables=None, **info): if len(projectables) != 3: raise ValueError("Expected 3 datasets, got %d" % (len(projectables), )) + return super(RGBCompositor, self).__call__(projectables, **info) areas = [projectable.attrs.get('area', None) for projectable in projectables] @@ -624,54 +613,29 @@ def __call__(self, projectables, nonprojectables=None, **info): return the_data -class BWCompositor(CompositeBase): - - def __call__(self, projectables, nonprojectables=None, **info): - - import warnings - warnings.warn("RGBCompositor is deprecated, use GenericCompositor " - "instead.", DeprecationWarning) - - if len(projectables) != 1: - raise ValueError("Expected 1 dataset, got %d" % - (len(projectables), )) - - info = combine_info(*projectables) - info['name'] = self.info['name'] - info['standard_name'] = self.info['standard_name'] - - return Dataset(projectables[0].copy(), **info.copy()) - - class GenericCompositor(CompositeBase): modes = {1: 'L', 2: 'LA', 3: 'RGB', 4: 'RGBA'} - def __call__(self, projectables, nonprojectables=None, **info): - - num = len(projectables) - mode = self.modes[num] - + def _concat_datasets(self, projectables, mode): try: - data = np.rollaxis(np.ma.dstack([projectable for projectable - in projectables]), axis=2) + data = xr.concat(projectables, 'bands') + data['bands'] = list(mode) except ValueError: raise IncompatibleAreas else: - areas = [projectable.info.get('area', None) + areas = [projectable.attrs.get('area', None) for projectable in projectables] areas = [area for area in areas if area is not None] if areas and areas.count(areas[0]) != len(areas): raise IncompatibleAreas - info = combine_info(*projectables) - info.update(self.info) - # FIXME: should this be done here ? - info["wavelength"] = None - info.pop("units", None) + return data + + def _get_sensors(self, projectables): sensor = set() for projectable in projectables: - current_sensor = projectable.info.get("sensor", None) + current_sensor = projectable.attrs.get("sensor", None) if current_sensor: if isinstance(current_sensor, (str, bytes, six.text_type)): sensor.add(current_sensor) @@ -681,9 +645,64 @@ def __call__(self, projectables, nonprojectables=None, **info): sensor = None elif len(sensor) == 1: sensor = list(sensor)[0] - info["sensor"] = sensor - info["mode"] = mode - return Dataset(data=data, **info) + return sensor + + def _get_times(self, projectables): + try: + times = [proj['time'][0].values for proj in projectables] + except KeyError: + pass + else: + # Is there a more gracious way to handle this ? + if np.max(times) - np.min(times) > np.timedelta64(1, 's'): + raise IncompatibleTimes + else: + mid_time = (np.max(times) - np.min(times)) / 2 + np.min(times) + projectables[0]['time'] = [mid_time] + projectables[1]['time'] = [mid_time] + projectables[2]['time'] = [mid_time] + return times + + def __call__(self, projectables, nonprojectables=None, **attrs): + + num = len(projectables) + mode = self.modes[num] + if len(projectables) > 1: + data = self._concat_datasets(projectables, mode) + else: + data = projectables[0] + + # TODO: How should we handle times? + + new_attrs = combine_metadata(*projectables) + # FIXME: in what situations are the vals None? + # In what situations do we not want those? + # What if the user is forcing it? + new_attrs.update({key: val + for (key, val) in attrs.items() + if val is not None}) + new_attrs.update(self.attrs) + new_attrs["sensor"] = self._get_sensors(projectables) + new_attrs["mode"] = mode + # TODO: Should these always be removed? + # TODO: What if the user specifies them? + if len(projectables) > 1: + new_attrs["wavelength"] = None + new_attrs.pop("units", None) + new_attrs.pop('calibration', None) + new_attrs.pop('modifiers', None) + return xr.DataArray(data=data, **new_attrs) + + +class BWCompositor(GenericCompositor): + + def __call__(self, projectables, nonprojectables=None, **info): + + import warnings + warnings.warn("BWCompositor is deprecated, use GenericCompositor " + "instead.", DeprecationWarning) + + return super(BWCompositor, self).__call__(projectables, **info) class ColormapCompositor(GenericCompositor): @@ -820,10 +839,10 @@ def __call__(self, projectables, lim_low=85., lim_high=95., *args, **projectables[0].info) full_data.append(data) - res = GenericCompositor.__call__(self, (full_data[0], - full_data[1], - full_data[2]), - *args, **kwargs) + res = super(DayNightCompositor, self).__call__((full_data[0], + full_data[1], + full_data[2]), + *args, **kwargs) except ValueError: raise IncompatibleAreas @@ -860,9 +879,9 @@ def __call__(self, projectables, *args, **kwargs): try: ch1 = sub_arrays(projectables[0], projectables[1]) ch2 = sub_arrays(projectables[2], projectables[3]) - res = GenericCompositor.__call__(self, (ch1, ch2, + res = super(Airmass, self).__call__((ch1, ch2, projectables[0]), - *args, **kwargs) + *args, **kwargs) except ValueError: raise IncompatibleAreas return res @@ -884,12 +903,11 @@ def __call__(self, projectables, *args, **kwargs): +--------------------+--------------------+--------------------+ """ try: - res = GenericCompositor.__call__(self, - (projectables[3] - projectables[4], - projectables[2] - - projectables[5], - projectables[1] - projectables[0]), - *args, **kwargs) + ch1 = sub_arrays(projectables[3], projectables[4]) + ch2 = sub_arrays(projectables[2], projectables[5]) + ch3 = sub_arrays(projectables[1], projectables[0]) + res = super(Convection, self).__call__((ch1, ch2, ch3), + *args, **kwargs) except ValueError: raise IncompatibleAreas return res @@ -926,8 +944,9 @@ def __call__(self, projectables, *args, **kwargs): ch1 = sub_arrays(projectables[2], projectables[1]) ch2 = sub_arrays(projectables[1], projectables[0]) - res = GenericCompositor.__call__(self, (ch1, ch2, - projectables[1]), *args, **kwargs) + res = super(Dust, self).__call__((ch1, ch2, + projectables[1]), + *args, **kwargs) except ValueError: raise IncompatibleAreas @@ -957,8 +976,8 @@ def __call__(self, projectables, *args, **kwargs): ch2 = ndvi * vis08 + (1 - ndvi) * vis06 ch2.attrs = vis08.attrs - res = GenericCompositor.__call__(self, (ch1, ch2, ch3), - *args, **kwargs) + res = super(RealisticColors, self).__call__((ch1, ch2, ch3), + *args, **kwargs) except ValueError: raise IncompatibleAreas return res From 501ff09c2db3084c8587199f8218a8d954e4dee1 Mon Sep 17 00:00:00 2001 From: davidh-ssec Date: Fri, 9 Feb 2018 21:15:58 -0600 Subject: [PATCH 21/23] Fix GenericCompositor location in file so it can subclassed --- satpy/composites/__init__.py | 81 +++++++----------------------------- 1 file changed, 14 insertions(+), 67 deletions(-) diff --git a/satpy/composites/__init__.py b/satpy/composites/__init__.py index 9b774a6a6f..c46bd79e56 100644 --- a/satpy/composites/__init__.py +++ b/satpy/composites/__init__.py @@ -546,73 +546,6 @@ def __call__(self, projectables, nonprojectables=None, **info): return Dataset(projectables[0] - projectables[1], **info) -class RGBCompositor(GenericCompositor): - - def __call__(self, projectables, nonprojectables=None, **info): - - import warnings - warnings.warn("RGBCompositor is deprecated, use GenericCompositor " - "instead.", DeprecationWarning) - - if len(projectables) != 3: - raise ValueError("Expected 3 datasets, got %d" % - (len(projectables), )) - return super(RGBCompositor, self).__call__(projectables, **info) - - areas = [projectable.attrs.get('area', None) - for projectable in projectables] - areas = [area for area in areas if area is not None] - if areas and areas.count(areas[0]) != len(areas): - raise IncompatibleAreas - try: - times = [proj['time'][0].values for proj in projectables] - except KeyError: - pass - else: - # Is there a more gracious way to handle this ? - if np.max(times) - np.min(times) > np.timedelta64(1, 's'): - raise IncompatibleTimes - else: - mid_time = (np.max(times) - np.min(times)) / 2 + np.min(times) - projectables[0]['time'] = [mid_time] - projectables[1]['time'] = [mid_time] - projectables[2]['time'] = [mid_time] - try: - the_data = xr.concat(projectables, 'bands') - the_data['bands'] = ['R', 'G', 'B'] - except ValueError: - raise IncompatibleAreas - - attrs = combine_metadata(*projectables) - attrs.update({key: val - for (key, val) in info.items() - if val is not None}) - attrs.update(self.attrs) - # FIXME: should this be done here ? - attrs["wavelength"] = None - attrs.pop("units", None) - sensor = set() - for projectable in projectables: - current_sensor = projectable.attrs.get("sensor", None) - if current_sensor: - if isinstance(current_sensor, (str, bytes, six.text_type)): - sensor.add(current_sensor) - else: - sensor |= current_sensor - if len(sensor) == 0: - sensor = None - elif len(sensor) == 1: - sensor = list(sensor)[0] - attrs["sensor"] = sensor - attrs["mode"] = "RGB" - the_data.attrs.update(attrs) - the_data.attrs.pop('calibration', None) - the_data.attrs.pop('modifiers', None) - the_data.name = the_data.attrs['name'] - - return the_data - - class GenericCompositor(CompositeBase): modes = {1: 'L', 2: 'LA', 3: 'RGB', 4: 'RGBA'} @@ -694,6 +627,20 @@ def __call__(self, projectables, nonprojectables=None, **attrs): return xr.DataArray(data=data, **new_attrs) +class RGBCompositor(GenericCompositor): + + def __call__(self, projectables, nonprojectables=None, **info): + + import warnings + warnings.warn("RGBCompositor is deprecated, use GenericCompositor " + "instead.", DeprecationWarning) + + if len(projectables) != 3: + raise ValueError("Expected 3 datasets, got %d" % + (len(projectables), )) + return super(RGBCompositor, self).__call__(projectables, **info) + + class BWCompositor(GenericCompositor): def __call__(self, projectables, nonprojectables=None, **info): From 175318ced1d3907f0290aacc5f664483c5fd8c34 Mon Sep 17 00:00:00 2001 From: davidh-ssec Date: Sat, 10 Feb 2018 11:23:42 -0600 Subject: [PATCH 22/23] Fix GenericCompositor to handle inputs with varying times --- satpy/composites/__init__.py | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/satpy/composites/__init__.py b/satpy/composites/__init__.py index c46bd79e56..2ddab8e3ae 100644 --- a/satpy/composites/__init__.py +++ b/satpy/composites/__init__.py @@ -591,10 +591,7 @@ def _get_times(self, projectables): raise IncompatibleTimes else: mid_time = (np.max(times) - np.min(times)) / 2 + np.min(times) - projectables[0]['time'] = [mid_time] - projectables[1]['time'] = [mid_time] - projectables[2]['time'] = [mid_time] - return times + return mid_time def __call__(self, projectables, nonprojectables=None, **attrs): @@ -605,25 +602,26 @@ def __call__(self, projectables, nonprojectables=None, **attrs): else: data = projectables[0] - # TODO: How should we handle times? + # if inputs have a time coordinate that may differ slightly between + # themselves then find the mid time and use that as the single + # time coordinate value + time = self._get_times(projectables) + if time is not None: + data['time'] = [time] new_attrs = combine_metadata(*projectables) - # FIXME: in what situations are the vals None? - # In what situations do we not want those? - # What if the user is forcing it? + # remove metadata that shouldn't make sense in a composite + new_attrs["wavelength"] = None + new_attrs.pop("units", None) + new_attrs.pop('calibration', None) + new_attrs.pop('modifiers', None) + new_attrs.update({key: val for (key, val) in attrs.items() if val is not None}) new_attrs.update(self.attrs) new_attrs["sensor"] = self._get_sensors(projectables) new_attrs["mode"] = mode - # TODO: Should these always be removed? - # TODO: What if the user specifies them? - if len(projectables) > 1: - new_attrs["wavelength"] = None - new_attrs.pop("units", None) - new_attrs.pop('calibration', None) - new_attrs.pop('modifiers', None) return xr.DataArray(data=data, **new_attrs) From 0bd8ae5460a6e52f33bff52dfca006138f0c03a8 Mon Sep 17 00:00:00 2001 From: davidh-ssec Date: Sat, 10 Feb 2018 11:23:59 -0600 Subject: [PATCH 23/23] Fix abi l1b slicing order --- satpy/readers/abi_l1b.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/satpy/readers/abi_l1b.py b/satpy/readers/abi_l1b.py index 3879e9ff4d..efdda166b2 100644 --- a/satpy/readers/abi_l1b.py +++ b/satpy/readers/abi_l1b.py @@ -66,7 +66,7 @@ def get_dataset(self, key, info, """Load a dataset.""" logger.debug('Reading in get_dataset %s.', key.name) - radiances = self.nc["Rad"][xslice, yslice].expand_dims('time') + radiances = self.nc["Rad"][yslice, xslice].expand_dims('time') res = self.calibrate(radiances)