Skip to content

Commit

Permalink
Merge branch 'main' into feat-comp-llm-cloud-mask
Browse files Browse the repository at this point in the history
  • Loading branch information
gerritholl committed Jan 24, 2025
2 parents 480a58b + 3990f37 commit b002b03
Show file tree
Hide file tree
Showing 7 changed files with 428 additions and 127 deletions.
108 changes: 108 additions & 0 deletions satpy/composites/lightning.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (c) 2019 Satpy developers
#
# This file is part of satpy.
#
# satpy 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.
#
# satpy 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
# satpy. If not, see <http://www.gnu.org/licenses/>.
"""Composite classes for the LI instrument."""

import logging

import numpy as np
import xarray as xr

from satpy.composites import CompositeBase

LOG = logging.getLogger(__name__)


class LightningTimeCompositor(CompositeBase):
"""Class used to create the flash_age compositor usefull for lighting event visualisation.
The datas used are dates related to the lightning event that should be normalised between
0 and 1. The value 1 corresponds to the latest lightning event and the value 0 corresponds
to the latest lightning event - time_range. The time_range is defined in the satpy/etc/composites/li.yaml
and is in minutes.
"""
def __init__(self, name, prerequisites=None, optional_prerequisites=None, **kwargs):
"""Initialisation of the class."""
super().__init__(name, prerequisites, optional_prerequisites, **kwargs)
# Get the time_range which is in minute
self.time_range = self.attrs["time_range"]
self.standard_name = self.attrs["standard_name"]
self.reference_time_attr = self.attrs["reference_time"]


def _normalize_time(self, data:xr.DataArray, attrs:dict) -> xr.DataArray:
"""Normalize the time in the range between [end_time, end_time - time_range].
The range of the normalised data is between 0 and 1 where 0 corresponds to the date end_time - time_range
and 1 to the end_time. Where end_times represent the latest lightning event and time_range is the range of
time you want to see the event.The dates that are earlier to end_time - time_range are removed.
Args:
data (xr.DataArray): datas containing dates to be normalised
attrs (dict): Attributes suited to the flash_age composite
Returns:
xr.DataArray: Normalised time
"""
# Compute the maximum time value
end_time = np.array(np.datetime64(data.attrs[self.reference_time_attr]))
# Compute the minimum time value based on the time range
begin_time = end_time - np.timedelta64(self.time_range, "m")
# Drop values that are bellow begin_time
condition_time = data >= begin_time
condition_time_computed = condition_time.compute()
data = data.where(condition_time_computed, drop=True)
# exit if data is empty afer filtering
if data.size == 0 :
LOG.error(f"All the flash_age events happened before {begin_time}")
raise ValueError(f"Invalid data: data size is zero. All flash_age "
f"events occurred before the specified start time ({begin_time})."
)
# Normalize the time values
normalized_data = (data - begin_time) / (end_time - begin_time)
# Ensure the result is still an xarray.DataArray
return xr.DataArray(normalized_data, dims=data.dims, coords=data.coords, attrs=attrs)


@staticmethod
def _update_missing_metadata(existing_attrs, new_attrs):
for key, val in new_attrs.items():
if key not in existing_attrs and val is not None:
existing_attrs[key] = val

def _redefine_metadata(self,attrs:dict)->dict:
"""Modify the standard_name and name metadatas.
Args:
attrs (dict): data's attributes
Returns:
dict: atualised attributes
"""
attrs["name"] = self.standard_name
attrs["standard_name"] = self.standard_name
# Attributes to describe the values range
return attrs


def __call__(self,projectables, nonprojectables=None, **attrs):
"""Normalise the dates."""
data = projectables[0]
new_attrs = data.attrs.copy()
self._update_missing_metadata(new_attrs, attrs)
new_attrs = self._redefine_metadata(new_attrs)
return self._normalize_time(data, new_attrs)
149 changes: 78 additions & 71 deletions satpy/etc/composites/fci.yaml
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
sensor_name: visir/fci

composites:
### L2
### L2
binary_cloud_mask:
# This will set all clear pixels to '0', all pixels with cloudy features (meteorological/dust/ash clouds) to '1' and
# missing/undefined pixels to 'nan'. This can be used for the official EUMETSAT cloud mask product (CLM).
compositor: !!python/name:satpy.composites.CategoricalDataCompositor
prerequisites:
- name: 'cloud_state'
lut: [ .nan, 0, 1, 1, 1, 1, 1, 1, 0, .nan ]
- name: "cloud_state"
lut: [.nan, 0, 1, 1, 1, 1, 1, 1, 0, .nan]
standard_name: binary_cloud_mask

### Night Layers
### Night Layers
night_ir105:
compositor: !!python/name:satpy.composites.SingleBandCompositor
prerequisites:
Expand Down Expand Up @@ -41,7 +41,7 @@ composites:
- night_ir_alpha
- _night_background_hires

### Green Corrections
### Green Corrections
ndvi_hybrid_green:
description: >
The FCI green band at 0.51 µm deliberately misses the chlorophyll band, such that
Expand All @@ -58,7 +58,7 @@ composites:
- name: vis_06
modifiers: [sunz_corrected, rayleigh_corrected, sunz_reduced]
- name: vis_08
modifiers: [sunz_corrected, sunz_reduced ]
modifiers: [sunz_corrected, sunz_reduced]
standard_name: toa_bidirectional_reflectance

ndvi_hybrid_green_raw:
Expand All @@ -76,18 +76,18 @@ composites:
ndvi_hybrid_green_fully_sunzencorrected:
description: Same as ndvi_hybrid_green, but without Sun-zenith reduction
compositor: !!python/name:satpy.composites.spectral.NDVIHybridGreen
limits: [ 0.15, 0.05 ]
limits: [0.15, 0.05]
strength: 3.0
prerequisites:
- name: vis_05
modifiers: [ sunz_corrected, rayleigh_corrected ]
modifiers: [sunz_corrected, rayleigh_corrected]
- name: vis_06
modifiers: [ sunz_corrected, rayleigh_corrected ]
modifiers: [sunz_corrected, rayleigh_corrected]
- name: vis_08
modifiers: [ sunz_corrected ]
modifiers: [sunz_corrected]
standard_name: toa_bidirectional_reflectance

### True Color
### True Color
true_color:
compositor: !!python/name:satpy.composites.SelfSharpenedRGB
description: >
Expand Down Expand Up @@ -190,7 +190,7 @@ composites:
- name: vis_04
standard_name: true_color_reproduction_color_stretch

### True Color with LI lightning
### True Color with LI lightning

true_color_with_night_ir105_acc_flash:
compositor: !!python/name:satpy.composites.BackgroundCompositor
Expand Down Expand Up @@ -227,74 +227,81 @@ composites:
- group_radiance_alpha
- true_color_with_night_ir105

### GeoColor
true_color_with_night_ir105_flash_age:
compositor: !!python/name:satpy.composites.BackgroundCompositor
standard_name: imager_with_lightning
prerequisites:
- flash_age
- true_color_with_night_ir105

### GeoColor
geo_color:
compositor: !!python/name:satpy.composites.DayNightCompositor
description: >
GeoColor is a multi-layer blended RGB composite where the day-time part of the image is represented by true
color imagery and the nighttime part of the image by a three layer vertically blended stack composed of a
high-level cloud layer (single IR window channel), a low-level cloud layer (IR split window) and a static
surface terrain layer with city lights (NASA Black Marble).
references:
Research Article: https://journals.ametsoc.org/view/journals/atot/37/3/JTECH-D-19-0134.1.xml
lim_low: 78
lim_high: 88
standard_name: geo_color_day_night_blend
prerequisites:
- true_color
- geo_color_night
compositor: !!python/name:satpy.composites.DayNightCompositor
description: >
GeoColor is a multi-layer blended RGB composite where the day-time part of the image is represented by true
color imagery and the nighttime part of the image by a three layer vertically blended stack composed of a
high-level cloud layer (single IR window channel), a low-level cloud layer (IR split window) and a static
surface terrain layer with city lights (NASA Black Marble).
references:
Research Article: https://journals.ametsoc.org/view/journals/atot/37/3/JTECH-D-19-0134.1.xml
lim_low: 78
lim_high: 88
standard_name: geo_color_day_night_blend
prerequisites:
- true_color
- geo_color_night

geo_color_high_clouds:
standard_name: geo_color_high_clouds
compositor: !!python/name:satpy.composites.HighCloudCompositor
prerequisites:
- name: ir_105
standard_name: geo_color_high_clouds
compositor: !!python/name:satpy.composites.HighCloudCompositor
prerequisites:
- name: ir_105

geo_color_low_clouds:
standard_name: geo_color_low_clouds
compositor: !!python/name:satpy.composites.LowCloudCompositor
values_water: 0
values_land: 100
range_water: [0.0, 4.0]
range_land: [1.5, 4.0]
prerequisites:
- compositor: !!python/name:satpy.composites.DifferenceCompositor
prerequisites:
- name: ir_105
- name: ir_38
- name: ir_105
- compositor: !!python/name:satpy.composites.StaticImageCompositor
standard_name: land_water_mask
url: "https://zenodo.org/records/10076199/files/gshhs_land_water_mask_3km_i.tif"
known_hash: "sha256:96df83c57416217e191f95dde3d3c1ce0373a8fc220e929228873db246ca3569"
standard_name: geo_color_low_clouds
compositor: !!python/name:satpy.composites.LowCloudCompositor
values_water: 0
values_land: 100
range_water: [0.0, 4.0]
range_land: [1.5, 4.0]
prerequisites:
- compositor: !!python/name:satpy.composites.DifferenceCompositor
prerequisites:
- name: ir_105
- name: ir_38
- name: ir_105
- compositor: !!python/name:satpy.composites.StaticImageCompositor
standard_name: land_water_mask
url: "https://zenodo.org/records/10076199/files/gshhs_land_water_mask_3km_i.tif"
known_hash: "sha256:96df83c57416217e191f95dde3d3c1ce0373a8fc220e929228873db246ca3569"

geo_color_background_with_low_clouds:
compositor: !!python/name:satpy.composites.BackgroundCompositor
standard_name: night_ir_with_background
prerequisites:
- geo_color_low_clouds
- _night_background_hires
compositor: !!python/name:satpy.composites.BackgroundCompositor
standard_name: night_ir_with_background
prerequisites:
- geo_color_low_clouds
- _night_background_hires

geo_color_night:
compositor: !!python/name:satpy.composites.BackgroundCompositor
standard_name: night_ir_with_background
prerequisites:
- geo_color_high_clouds
- geo_color_background_with_low_clouds
compositor: !!python/name:satpy.composites.BackgroundCompositor
standard_name: night_ir_with_background
prerequisites:
- geo_color_high_clouds
- geo_color_background_with_low_clouds

### IR-Sandwich
### IR-Sandwich
ir_sandwich:
compositor: !!python/name:satpy.composites.SandwichCompositor
standard_name: ir_sandwich
prerequisites:
- name: 'vis_06'
modifiers: [ sunz_corrected ]
- name: "vis_06"
modifiers: [sunz_corrected]
- name: colorized_ir_clouds

colorized_ir_clouds:
compositor: !!python/name:satpy.composites.SingleBandCompositor
prerequisites:
- name: 'ir_105'
- name: "ir_105"
standard_name: colorized_ir_clouds

ir_sandwich_with_night_colorized_ir_clouds:
Expand All @@ -306,7 +313,7 @@ composites:
- ir_sandwich
- colorized_ir_clouds

### other RGBs
### other RGBs
cloud_type:
description: >
Equal to cimss_cloud_type recipe, but with additional sunz_reducer modifier to avoid saturation at the terminator.
Expand All @@ -316,11 +323,11 @@ composites:
compositor: !!python/name:satpy.composites.GenericCompositor
prerequisites:
- name: nir_13
modifiers: [ sunz_corrected, sunz_reduced ]
modifiers: [sunz_corrected, sunz_reduced]
- name: vis_06
modifiers: [ sunz_corrected, sunz_reduced ]
modifiers: [sunz_corrected, sunz_reduced]
- name: nir_16
modifiers: [ sunz_corrected, sunz_reduced ]
modifiers: [sunz_corrected, sunz_reduced]
standard_name: cimss_cloud_type

cloud_type_with_night_ir105:
Expand Down Expand Up @@ -416,12 +423,12 @@ composites:
Recipe: https://resources.eumetrain.org/RGBguide/recipes/RGB_recipes.pdf
compositor: !!python/name:satpy.composites.GenericCompositor
prerequisites:
- name: vis_08
modifiers: [sunz_corrected]
- name: nir_16
modifiers: [sunz_corrected]
- name: ir_38
modifiers: [nir_reflectance]
- name: vis_08
modifiers: [sunz_corrected]
- name: nir_16
modifiers: [sunz_corrected]
- name: ir_38
modifiers: [nir_reflectance]
standard_name: snow

masked_colorized_low_level_moisture:
Expand Down
Loading

0 comments on commit b002b03

Please sign in to comment.