From aa52480e53aef208c134d9d6513c44c034ad4b55 Mon Sep 17 00:00:00 2001 From: Simon Proud Date: Tue, 19 Dec 2023 15:45:15 +0000 Subject: [PATCH] Add AHI fires comp --- satpy/composites/fires.py | 112 ++++++++++++++++++++++++++++ satpy/etc/composites/ahi.yaml | 64 ++++++++++++++++ satpy/etc/enhancements/generic.yaml | 17 +++++ 3 files changed, 193 insertions(+) create mode 100644 satpy/composites/fires.py diff --git a/satpy/composites/fires.py b/satpy/composites/fires.py new file mode 100644 index 0000000000..216e93637c --- /dev/null +++ b/satpy/composites/fires.py @@ -0,0 +1,112 @@ +# Copyright (c) 2023 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 . +"""Composite classes for spectral adjustments.""" + +import logging + +from satpy.composites import GenericCompositor +from satpy.dataset import combine_metadata + +LOG = logging.getLogger(__name__) + + +class MultiFireCompositor(GenericCompositor): + """Combines an RGB image, such as true_color, with a fire radiative power dataset.""" + + def __init__(self, min_frp=0., max_frp=30., **kwargs): + """Collect custom configuration values. + + Args: + min_frp (float): Minimum value of FRP to use in the composite. + max_frp (float): Maximum value of FRP to use in the composite. + **kwargs: Additional keyword arguments passed to GenericCompositor. + """ + self.min_frp = min_frp + self.max_frp = max_frp + + super(MultiFireCompositor, self).__init__(**kwargs) + + def __call__(self, projectables, **kwargs): + """Generate the composite.""" + import numpy as np + + projectables = self.match_data_arrays(projectables) + # At least one composite is requested. + + the_frp = projectables[0] + + frp_data = the_frp.data + + frp_data = np.where(np.isfinite(frp_data), frp_data, np.nan) + frp_data = np.where(frp_data > self.max_frp, self.max_frp, frp_data) + frp_data = np.where(frp_data < self.min_frp, self.min_frp, frp_data) + frp_data = np.where(frp_data < self.min_frp, np.nan, frp_data) + frp_data = frp_data / self.max_frp + + + frp_data = frp_data / np.nanmax(frp_data) + + the_frp.data = frp_data * 255. + + return super(MultiFireCompositor, self).__call__([the_frp], **kwargs) + + +class FireRadiativePowerComposite(GenericCompositor): + """Combines an RGB image, such as true_color, with a fire radiative power dataset.""" + + def __init__(self, name, do_load_lsm=True, **kwargs): + """Collect custom configuration values.""" + self.do_load_lsm = False#do_load_lsm + super(FireRadiativePowerComposite, self).__init__(name, **kwargs) + + + def __call__(self, projectables, **attrs): + """Generate the composite.""" + try: + from pyfires.PYF_basic import sort_l1 + from pyfires.PYF_detection import run_dets + except ImportError: + raise ImportError("The `pyfires` library is required to run the FireRadiativePowerComposite composite.") + + projectables = self.match_data_arrays(projectables) + # At least one composite is requested. + + if len(projectables) != 5: + raise ValueError("FireRadiativePowerComposite requires input radiance data for channels near 0.6, " + "3.8 and 10.5 micron. Brightness temperature data is also required for 3.8 and 10.5 " + "micron.") + + band_dict = {"vi1_band": projectables[0].attrs["name"], + "mir_band": projectables[1].attrs["name"], + "lwi_band": projectables[2].attrs["name"]} + + data_dict = sort_l1(projectables[0], projectables[1], + projectables[2], projectables[3], + projectables[4], + band_dict, do_load_lsm=self.do_load_lsm) + + + fire_dets, frp_data = run_dets(data_dict) + frp_out = projectables[0].copy() + frp_out.data = frp_data + frp_out.attrs["units"] = "MW" + frp_out.attrs["standard_name"] = "fire_radiative_power" + frp_out.attrs["long_name"] = "Fire Radiative Power" + frp_out.attrs["name"] = "frp" + + frp_out.attrs = combine_metadata(*projectables) + + return super().__call__((frp_out,), **attrs) diff --git a/satpy/etc/composites/ahi.yaml b/satpy/etc/composites/ahi.yaml index 5d633056be..680d0351f9 100644 --- a/satpy/etc/composites/ahi.yaml +++ b/satpy/etc/composites/ahi.yaml @@ -515,3 +515,67 @@ composites: prerequisites: - geo_color_high_clouds - geo_color_background_with_low_clouds + + fire_radiative_power: + compositor: !!python/name:satpy.composites.fires.FireRadiativePowerComposite + standard_name: fire_radiative_power + prerequisites: + - name: B03 + calibration: radiance + - name: B07 + calibration: radiance + - name: B13 + calibration: radiance + - name: B07 + calibration: brightness_temperature + - name: B13 + calibration: brightness_temperature + + + tcr_night_ir: + # JMA True Color Reproduction complete composite with corrected and uncorrected blend. + # http://www.jma.go.jp/jma/jma-eng/satellite/introduction/TCR.html + # Blended at night with the `cloudtop` composite. + compositor: !!python/name:satpy.composites.DayNightCompositor + lim_low: 84. + lim_high: 92. + prerequisites: + - true_color_reproduction + - cloudtop + + true_color_flames: + compositor: !!python/name:satpy.composites.BackgroundCompositor + standard_name: true_color_flames + prerequisites: + - fire_rgb_masked_alpha + - tcr_night_ir + + multi_fires: + compositor: !!python/name:satpy.composites.fires.MultiFireCompositor + standard_name: multi_fires + prerequisites: + - fire_radiative_power + + fire_rgb_masked_alpha: + compositor: !!python/name:satpy.composites.MaskingCompositor + standard_name: fire_power_masked_alpha_col + conditions: + - method: isnan + transparency: 100 + - method: less + value: 2 + transparency: 100 + - method: less + value: 70 + transparency: 99 + - method: less + value: 150 + transparency: 90 + - method: less + value: 220 + transparency: 30 + prerequisites: + # Composite + - name: multi_fires + # Data used in masking + - name: multi_fires diff --git a/satpy/etc/enhancements/generic.yaml b/satpy/etc/enhancements/generic.yaml index 25680d6db9..2de3bc195f 100644 --- a/satpy/etc/enhancements/generic.yaml +++ b/satpy/etc/enhancements/generic.yaml @@ -1230,3 +1230,20 @@ enhancements: stretch: crude min_stretch: [0,0,0] max_stretch: [1,1,1] + + fire_power_masked_alpha_col: + standard_name: fire_power_masked_alpha_col + operations: + - name: colorize + method: !!python/name:satpy.enhancements.colorize + kwargs: + palettes: + - { colors: ylorrd, min_value: 0, max_value: 250, reverse: true} + + multi_fires: + standard_name: multi_fires + operations: + - name: stretch + method: !!python/name:satpy.enhancements.stretch + kwargs: + stretch: crude