pytroll / pytroll/satpy

Loading an image with generic_image, then writing with geotiff, changes the image

Open
#3,239 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
1.2k
Forks
335
Avg merge
1d 18h
Merged PRs (30d)
10

Description

Describe the bug

When I load an image with the generic_image reader and immediately write it out again, the image changes. This happens because the generic_image reader returns float data, and then a default enhancement gets applied. However, not enhancing the data at all is even worse.

To Reproduce

from satpy import Scene
from glob import glob
seviri_files = glob("/media/nas/x21308/scratch/SEVIRI/202103300900/H-000*")
sc = Scene(filenames={"seviri_l1b_hrit": seviri_files})
sc.load(["natural_color"])
sc.save_datasets(writer="geotiff", filename="/tmp/natural-color-1.tif")

sc2 = Scene(filenames={"generic_image": ["/tmp/natural-color-1.tif"]})
sc2.load(["image"])
sc2.save_datasets(writer="geotiff", filename="/tmp/natural-color-2.tif")

Expected behavior

I expect both images to look the same.

Actual results

There is a difference, because the second image is getting re-enhanced:

[DEBUG: 2025-09-18 11:22:19 : satpy.readers.core.yaml_reader] Reading ('/home/gholl/checkouts/satpy/satpy/etc/readers/seviri_l1b_hrit.yaml',)
[DEBUG: 2025-09-18 11:22:19 : satpy.readers.core.yaml_reader] Assigning to seviri_l1b_hrit: ['/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-HRV______-000006___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-HRV______-000017___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-HRV______-000018___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-HRV______-000004___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-HRV______-000010___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-HRV______-000011___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-HRV______-000016___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-HRV______-000019___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-HRV______-000009___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-HRV______-000020___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-HRV______-000014___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-HRV______-000012___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-HRV______-000013___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-HRV______-000001___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-HRV______-000008___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-HRV______-000022___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-HRV______-000023___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-HRV______-000015___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-HRV______-000002___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-HRV______-000024___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-HRV______-000005___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-HRV______-000021___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-HRV______-000007___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-HRV______-000003___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_016___-000004___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_016___-000008___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_016___-000002___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_016___-000001___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_016___-000007___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_016___-000005___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_016___-000003___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_016___-000006___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_039___-000003___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_039___-000008___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_039___-000007___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_039___-000004___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_039___-000002___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_039___-000006___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_039___-000005___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_039___-000001___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_087___-000002___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_087___-000003___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_087___-000004___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_087___-000007___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_087___-000005___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_087___-000001___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_087___-000006___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_087___-000008___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_097___-000006___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_097___-000002___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_097___-000001___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_097___-000008___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_097___-000005___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_097___-000004___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_097___-000003___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_097___-000007___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_108___-000001___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_108___-000006___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_108___-000004___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_108___-000007___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_108___-000005___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_108___-000003___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_108___-000008___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_108___-000002___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_120___-000006___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_120___-000001___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_120___-000004___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_120___-000008___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_120___-000002___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_120___-000005___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_120___-000003___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_120___-000007___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_134___-000007___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_134___-000008___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_134___-000003___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_134___-000004___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_134___-000006___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_134___-000001___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_134___-000002___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-IR_134___-000005___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-VIS006___-000008___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-VIS006___-000002___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-VIS006___-000007___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-VIS006___-000005___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-VIS006___-000006___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-VIS006___-000001___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-VIS006___-000003___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-VIS006___-000004___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-VIS008___-000001___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-VIS008___-000003___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-VIS008___-000007___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-VIS008___-000008___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-VIS008___-000005___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-VIS008___-000006___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-VIS008___-000004___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-VIS008___-000002___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-WV_062___-000005___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-WV_062___-000006___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-WV_062___-000007___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-WV_062___-000003___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-WV_062___-000002___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-WV_062___-000001___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-WV_062___-000008___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-WV_062___-000004___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-WV_073___-000005___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-WV_073___-000003___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-WV_073___-000006___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-WV_073___-000002___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-WV_073___-000001___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-WV_073___-000004___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-WV_073___-000007___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-WV_073___-000008___-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-_________-PRO______-202103300900-__', '/media/nas/x21308/scratch/SEVIRI/202103300900/H-000-MSG4__-MSG4________-_________-EPI______-202103300900-__']
[INFO: 2025-09-18 11:22:19 : hrit_msg] No IMPF configuration field found in prologue.
[DEBUG: 2025-09-18 11:22:19 : satpy.composites.config_loader] Looking for composites config file seviri.yaml
[DEBUG: 2025-09-18 11:22:19 : pyorbital.tlefile] Path to the Pyorbital configuration (where e.g. platforms.txt is found): /home/gholl/miniforge3/envs/py313/lib/python3.13/site-packages/pyorbital/etc
[DEBUG: 2025-09-18 11:22:19 : satpy.composites.config_loader] Looking for composites config file visir.yaml
[DEBUG: 2025-09-18 11:22:19 : satpy.readers.core.yaml_reader] Requested orientation for Dataset None is 'native' (default). No flipping is applied.
[DEBUG: 2025-09-18 11:22:19 : satpy.readers.core.yaml_reader] Requested orientation for Dataset None is 'native' (default). No flipping is applied.
[DEBUG: 2025-09-18 11:22:19 : satpy.readers.core.yaml_reader] Requested orientation for Dataset None is 'native' (default). No flipping is applied.
[DEBUG: 2025-09-18 11:22:19 : satpy.modifiers.geometry] Applying sun zen correction
[DEBUG: 2025-09-18 11:22:19 : satpy.modifiers.geometry] Computing sun zenith angles.
[DEBUG: 2025-09-18 11:22:19 : satpy.modifiers.geometry] Apply the standard sun-zenith correction [1/cos(sunz)]
[DEBUG: 2025-09-18 11:22:19 : satpy.modifiers.geometry] Applying sun zen correction
[DEBUG: 2025-09-18 11:22:19 : satpy.modifiers.geometry] Computing sun zenith angles.
[DEBUG: 2025-09-18 11:22:19 : satpy.modifiers.geometry] Apply the standard sun-zenith correction [1/cos(sunz)]
[DEBUG: 2025-09-18 11:22:19 : satpy.modifiers.geometry] Applying sun zen correction
[DEBUG: 2025-09-18 11:22:19 : satpy.modifiers.geometry] Computing sun zenith angles.
[DEBUG: 2025-09-18 11:22:19 : satpy.modifiers.geometry] Apply the standard sun-zenith correction [1/cos(sunz)]
[DEBUG: 2025-09-18 11:22:19 : satpy.scene] Unloading dataset: DataID(name='IR_016', wavelength=WavelengthRange(min=1.5, central=1.64, max=1.78, unit='µm'), resolution=3000.403165817, calibration=<1>, modifiers=())
[DEBUG: 2025-09-18 11:22:19 : satpy.scene] Unloading dataset: DataID(name='VIS008', wavelength=WavelengthRange(min=0.74, central=0.81, max=0.88, unit='µm'), resolution=3000.403165817, calibration=<1>, modifiers=())
[DEBUG: 2025-09-18 11:22:19 : satpy.scene] Unloading dataset: DataID(name='VIS006', wavelength=WavelengthRange(min=0.56, central=0.635, max=0.71, unit='µm'), resolution=3000.403165817, calibration=<1>, modifiers=())
[DEBUG: 2025-09-18 11:22:19 : satpy.scene] Unloading dataset: DataID(name='IR_016', wavelength=WavelengthRange(min=1.5, central=1.64, max=1.78, unit='µm'), resolution=3000.403165817, calibration=<1>, modifiers=('sunz_corrected',))
[DEBUG: 2025-09-18 11:22:19 : satpy.scene] Unloading dataset: DataID(name='VIS008', wavelength=WavelengthRange(min=0.74, central=0.81, max=0.88, unit='µm'), resolution=3000.403165817, calibration=<1>, modifiers=('sunz_corrected',))
[DEBUG: 2025-09-18 11:22:19 : satpy.scene] Unloading dataset: DataID(name='VIS006', wavelength=WavelengthRange(min=0.56, central=0.635, max=0.71, unit='µm'), resolution=3000.403165817, calibration=<1>, modifiers=('sunz_corrected',))
[DEBUG: 2025-09-18 11:22:19 : satpy.writers.core.config] Reading ['/home/gholl/checkouts/satpy/satpy/etc/writers/geotiff.yaml']
[DEBUG: 2025-09-18 11:22:19 : rasterio.session] Could not import boto3, continuing with reduced functionality.
[DEBUG: 2025-09-18 11:22:20 : satpy.enhancements.enhancer] Adding enhancement configuration from file: /home/gholl/checkouts/satpy/satpy/etc/enhancements/generic.yaml
[DEBUG: 2025-09-18 11:22:20 : satpy.enhancements.enhancer] Adding enhancement configuration from file: /home/gholl/checkouts/pytroll-dwd-config/dev/enhancements/generic.yaml
[DEBUG: 2025-09-18 11:22:20 : satpy.enhancements.enhancer] Adding enhancement configuration from file: /home/gholl/checkouts/pytroll-dwd-config/oper/enhancements/generic.yaml
[DEBUG: 2025-09-18 11:22:20 : satpy.enhancements.enhancer] Adding enhancement configuration from file: /home/gholl/checkouts/satpy/satpy/etc/enhancements/seviri.yaml
[DEBUG: 2025-09-18 11:22:20 : satpy.enhancements.enhancer] Data for DataID(name='natural_color', resolution=3000.403165817) will be enhanced with options:
	[{'name': 'stretch', 'method': <function stretch at 0x7fde9f5716c0>, 'kwargs': {'stretch': 'crude', 'min_stretch': 0, 'max_stretch': 120}}, {'name': 'gamma', 'method': <function gamma at 0x7fde9f571760>, 'kwargs': {'gamma': 1.8}}]
[DEBUG: 2025-09-18 11:22:20 : trollimage.xrimage] Applying stretch crude with parameters {'min_stretch': 0, 'max_stretch': 120}
[DEBUG: 2025-09-18 11:22:20 : trollimage.xrimage] Applying gamma 1.8
[DEBUG: 2025-09-18 11:22:20 : rasterio.env] Entering env context: <rasterio.env.Env object at 0x7fde9f1541a0>
[DEBUG: 2025-09-18 11:22:20 : rasterio.env] Starting outermost env
[DEBUG: 2025-09-18 11:22:20 : rasterio.env] No GDAL environment exists
[DEBUG: 2025-09-18 11:22:20 : rasterio.env] New GDAL environment <rasterio._env.GDALEnv object at 0x7fdea26925f0> created
[DEBUG: 2025-09-18 11:22:20 : rasterio._filepath] Installing FilePath filesystem handler plugin...
[DEBUG: 2025-09-18 11:22:20 : rasterio._env] GDAL_DATA found in environment.
[DEBUG: 2025-09-18 11:22:20 : rasterio._env] PROJ_DATA found in environment.
[DEBUG: 2025-09-18 11:22:20 : rasterio._env] Started GDALEnv: self=<rasterio._env.GDALEnv object at 0x7fdea26925f0>.
[DEBUG: 2025-09-18 11:22:20 : rasterio.env] Entered env context: <rasterio.env.Env object at 0x7fde9f1541a0>
[DEBUG: 2025-09-18 11:22:20 : rasterio._base] Nodata success: 0, Nodata value: 0.000000
[DEBUG: 2025-09-18 11:22:20 : rasterio._base] Nodata success: 0, Nodata value: 0.000000
[DEBUG: 2025-09-18 11:22:20 : rasterio._base] Nodata success: 0, Nodata value: 0.000000
[DEBUG: 2025-09-18 11:22:20 : rasterio._base] Nodata success: 0, Nodata value: 0.000000
[DEBUG: 2025-09-18 11:22:20 : rasterio.env] Exiting env context: <rasterio.env.Env object at 0x7fde9f1541a0>
[DEBUG: 2025-09-18 11:22:20 : rasterio.env] Cleared existing <rasterio._env.GDALEnv object at 0x7fdea26925f0> options
[DEBUG: 2025-09-18 11:22:20 : rasterio._env] Stopped GDALEnv <rasterio._env.GDALEnv object at 0x7fdea26925f0>.
[DEBUG: 2025-09-18 11:22:20 : rasterio.env] Exiting outermost env
[DEBUG: 2025-09-18 11:22:20 : rasterio.env] Exited env context: <rasterio.env.Env object at 0x7fde9f1541a0>
[INFO: 2025-09-18 11:22:20 : satpy.writers.core.base] Computing and writing results...
[DEBUG: 2025-09-18 11:22:22 : satpy.readers.core.yaml_reader] Reading ('/home/gholl/checkouts/satpy/satpy/etc/readers/generic_image.yaml',)
[DEBUG: 2025-09-18 11:22:22 : satpy.readers.core.yaml_reader] Assigning to generic_image: ['/tmp/natural-color-1.tif']
[DEBUG: 2025-09-18 11:22:22 : rasterio.env] Entering env context: <rasterio.env.Env object at 0x7fde9f248a50>
[DEBUG: 2025-09-18 11:22:22 : rasterio.env] Starting outermost env
[DEBUG: 2025-09-18 11:22:22 : rasterio.env] No GDAL environment exists
[DEBUG: 2025-09-18 11:22:22 : rasterio.env] New GDAL environment <rasterio._env.GDALEnv object at 0x7fde9f2800d0> created
[DEBUG: 2025-09-18 11:22:22 : rasterio._env] GDAL_DATA found in environment.
[DEBUG: 2025-09-18 11:22:22 : rasterio._env] PROJ_DATA found in environment.
[DEBUG: 2025-09-18 11:22:22 : rasterio._env] Started GDALEnv: self=<rasterio._env.GDALEnv object at 0x7fde9f2800d0>.
[DEBUG: 2025-09-18 11:22:22 : rasterio.env] Entered env context: <rasterio.env.Env object at 0x7fde9f248a50>
[DEBUG: 2025-09-18 11:22:22 : rasterio._base] Sharing flag: 0
[DEBUG: 2025-09-18 11:22:22 : rasterio._base] Nodata success: 0, Nodata value: 0.000000
[DEBUG: 2025-09-18 11:22:22 : rasterio._base] Nodata success: 0, Nodata value: 0.000000
[DEBUG: 2025-09-18 11:22:22 : rasterio._base] Nodata success: 0, Nodata value: 0.000000
[DEBUG: 2025-09-18 11:22:22 : rasterio._base] Nodata success: 0, Nodata value: 0.000000
[DEBUG: 2025-09-18 11:22:22 : rasterio._base] Dataset <open DatasetReader name='/tmp/natural-color-1.tif' mode='r'> is started.
[DEBUG: 2025-09-18 11:22:22 : rasterio.env] Exiting env context: <rasterio.env.Env object at 0x7fde9f248a50>
[DEBUG: 2025-09-18 11:22:22 : rasterio.env] Cleared existing <rasterio._env.GDALEnv object at 0x7fde9f2800d0> options
[DEBUG: 2025-09-18 11:22:22 : rasterio._env] Stopped GDALEnv <rasterio._env.GDALEnv object at 0x7fde9f2800d0>.
[DEBUG: 2025-09-18 11:22:22 : rasterio.env] Exiting outermost env
[DEBUG: 2025-09-18 11:22:22 : rasterio.env] Exited env context: <rasterio.env.Env object at 0x7fde9f248a50>
[DEBUG: 2025-09-18 11:22:22 : rasterio.env] Entering env context: <rasterio.env.Env object at 0x7fde9f248a50>
[DEBUG: 2025-09-18 11:22:22 : rasterio.env] Starting outermost env
[DEBUG: 2025-09-18 11:22:22 : rasterio.env] No GDAL environment exists
[DEBUG: 2025-09-18 11:22:22 : rasterio.env] New GDAL environment <rasterio._env.GDALEnv object at 0x7fdea263b700> created
[DEBUG: 2025-09-18 11:22:22 : rasterio._env] GDAL_DATA found in environment.
[DEBUG: 2025-09-18 11:22:22 : rasterio._env] PROJ_DATA found in environment.
[DEBUG: 2025-09-18 11:22:22 : rasterio._env] Started GDALEnv: self=<rasterio._env.GDALEnv object at 0x7fdea263b700>.
[DEBUG: 2025-09-18 11:22:22 : rasterio.env] Entered env context: <rasterio.env.Env object at 0x7fde9f248a50>
[DEBUG: 2025-09-18 11:22:22 : rasterio._base] Sharing flag: 0
[DEBUG: 2025-09-18 11:22:22 : rasterio._base] Nodata success: 0, Nodata value: 0.000000
[DEBUG: 2025-09-18 11:22:22 : rasterio._base] Nodata success: 0, Nodata value: 0.000000
[DEBUG: 2025-09-18 11:22:22 : rasterio._base] Nodata success: 0, Nodata value: 0.000000
[DEBUG: 2025-09-18 11:22:22 : rasterio._base] Nodata success: 0, Nodata value: 0.000000
[DEBUG: 2025-09-18 11:22:22 : rasterio._base] Dataset <open DatasetReader name='/tmp/natural-color-1.tif' mode='r'> is started.
[DEBUG: 2025-09-18 11:22:22 : rasterio.env] Exiting env context: <rasterio.env.Env object at 0x7fde9f248a50>
[DEBUG: 2025-09-18 11:22:22 : rasterio.env] Cleared existing <rasterio._env.GDALEnv object at 0x7fdea263b700> options
[DEBUG: 2025-09-18 11:22:22 : rasterio._env] Stopped GDALEnv <rasterio._env.GDALEnv object at 0x7fdea263b700>.
[DEBUG: 2025-09-18 11:22:22 : rasterio.env] Exiting outermost env
[DEBUG: 2025-09-18 11:22:22 : rasterio.env] Exited env context: <rasterio.env.Env object at 0x7fde9f248a50>
[DEBUG: 2025-09-18 11:22:22 : satpy.composites.config_loader] Looking for composites config file images.yaml
[DEBUG: 2025-09-18 11:22:22 : satpy.composites.config_loader] No composite config found called images.yaml
[DEBUG: 2025-09-18 11:22:22 : satpy.readers.generic_image] Reading 'image.'
[DEBUG: 2025-09-18 11:22:22 : satpy.writers.core.config] Reading ['/home/gholl/checkouts/satpy/satpy/etc/writers/geotiff.yaml']
[DEBUG: 2025-09-18 11:22:22 : satpy.enhancements.enhancer] Adding enhancement configuration from file: /home/gholl/checkouts/satpy/satpy/etc/enhancements/generic.yaml
[DEBUG: 2025-09-18 11:22:22 : satpy.enhancements.enhancer] Adding enhancement configuration from file: /home/gholl/checkouts/pytroll-dwd-config/dev/enhancements/generic.yaml
[DEBUG: 2025-09-18 11:22:22 : satpy.enhancements.enhancer] Adding enhancement configuration from file: /home/gholl/checkouts/pytroll-dwd-config/oper/enhancements/generic.yaml
[DEBUG: 2025-09-18 11:22:22 : satpy.enhancements.enhancer] Data for DataID(name='image', modifiers=()) will be enhanced with options:
	[{'name': 'stretch', 'method': <function stretch at 0x7fde9f5716c0>, 'kwargs': {'stretch': 'linear'}}]
[DEBUG: 2025-09-18 11:22:22 : trollimage.xrimage] Applying stretch linear with parameters {}
[DEBUG: 2025-09-18 11:22:22 : trollimage.xrimage] Perform a linear contrast stretch.
[DEBUG: 2025-09-18 11:22:22 : trollimage.xrimage] Calculate the histogram quantiles: 
[DEBUG: 2025-09-18 11:22:22 : trollimage.xrimage] Left and right quantiles: 0.005 0.005
[DEBUG: 2025-09-18 11:22:22 : rasterio.env] Entering env context: <rasterio.env.Env object at 0x7fde9f4f36f0>
[DEBUG: 2025-09-18 11:22:22 : rasterio.env] Starting outermost env
[DEBUG: 2025-09-18 11:22:22 : rasterio.env] No GDAL environment exists
[DEBUG: 2025-09-18 11:22:22 : rasterio.env] New GDAL environment <rasterio._env.GDALEnv object at 0x7fde9f57e1a0> created
[DEBUG: 2025-09-18 11:22:22 : rasterio._env] GDAL_DATA found in environment.
[DEBUG: 2025-09-18 11:22:22 : rasterio._env] PROJ_DATA found in environment.
[DEBUG: 2025-09-18 11:22:22 : rasterio._env] Started GDALEnv: self=<rasterio._env.GDALEnv object at 0x7fde9f57e1a0>.
[DEBUG: 2025-09-18 11:22:22 : rasterio.env] Entered env context: <rasterio.env.Env object at 0x7fde9f4f36f0>
[DEBUG: 2025-09-18 11:22:22 : rasterio._base] Nodata success: 0, Nodata value: 0.000000
[DEBUG: 2025-09-18 11:22:22 : rasterio._base] Nodata success: 0, Nodata value: 0.000000
[DEBUG: 2025-09-18 11:22:22 : rasterio._base] Nodata success: 0, Nodata value: 0.000000
[DEBUG: 2025-09-18 11:22:22 : rasterio._base] Nodata success: 0, Nodata value: 0.000000
[DEBUG: 2025-09-18 11:22:22 : rasterio.env] Exiting env context: <rasterio.env.Env object at 0x7fde9f4f36f0>
[DEBUG: 2025-09-18 11:22:22 : rasterio.env] Cleared existing <rasterio._env.GDALEnv object at 0x7fde9f57e1a0> options
[DEBUG: 2025-09-18 11:22:22 : rasterio._env] Stopped GDALEnv <rasterio._env.GDALEnv object at 0x7fde9f57e1a0>.
[DEBUG: 2025-09-18 11:22:22 : rasterio.env] Exiting outermost env
[DEBUG: 2025-09-18 11:22:22 : rasterio.env] Exited env context: <rasterio.env.Env object at 0x7fde9f4f36f0>
[INFO: 2025-09-18 11:22:22 : satpy.writers.core.base] Computing and writing results...
[DEBUG: 2025-09-18 11:22:22 : rasterio._io] Output nodata value read from file: None
[DEBUG: 2025-09-18 11:22:22 : rasterio._io] Output nodata values: [None]
[DEBUG: 2025-09-18 11:22:22 : rasterio._io] all_valid: False
[DEBUG: 2025-09-18 11:22:22 : rasterio._io] mask_flags: ([<MaskFlags.per_dataset: 2>, <MaskFlags.alpha: 4>], [<MaskFlags.per_dataset: 2>, <MaskFlags.alpha: 4>], [<MaskFlags.per_dataset: 2>, <MaskFlags.alpha: 4>], [<MaskFlags.all_valid: 1>])
[DEBUG: 2025-09-18 11:22:22 : rasterio._io] Jump straight to _read()
[DEBUG: 2025-09-18 11:22:22 : rasterio._io] Window: Window(col_off=0, row_off=0, width=3712, height=3712)
[DEBUG: 2025-09-18 11:22:22 : rasterio._io] IO window xoff=0.0 yoff=0.0 width=3712.0 height=3712.0
[DEBUG: 2025-09-18 11:22:22 : rasterio._io] Output nodata value read from file: None
[DEBUG: 2025-09-18 11:22:22 : rasterio._io] Output nodata values: [None]
[DEBUG: 2025-09-18 11:22:22 : rasterio._io] all_valid: False
[DEBUG: 2025-09-18 11:22:22 : rasterio._io] mask_flags: ([<MaskFlags.per_dataset: 2>, <MaskFlags.alpha: 4>], [<MaskFlags.per_dataset: 2>, <MaskFlags.alpha: 4>], [<MaskFlags.per_dataset: 2>, <MaskFlags.alpha: 4>], [<MaskFlags.all_valid: 1>])
[DEBUG: 2025-09-18 11:22:22 : rasterio._io] Jump straight to _read()
[DEBUG: 2025-09-18 11:22:22 : rasterio._io] Window: Window(col_off=0, row_off=0, width=3712, height=3712)
[DEBUG: 2025-09-18 11:22:22 : rasterio._io] IO window xoff=0.0 yoff=0.0 width=3712.0 height=3712.0
[DEBUG: 2025-09-18 11:22:22 : rasterio._io] Output nodata value read from file: None
[DEBUG: 2025-09-18 11:22:22 : rasterio._io] Output nodata values: [None]
[DEBUG: 2025-09-18 11:22:22 : rasterio._io] all_valid: False
[DEBUG: 2025-09-18 11:22:22 : rasterio._io] mask_flags: ([<MaskFlags.per_dataset: 2>, <MaskFlags.alpha: 4>], [<MaskFlags.per_dataset: 2>, <MaskFlags.alpha: 4>], [<MaskFlags.per_dataset: 2>, <MaskFlags.alpha: 4>], [<MaskFlags.all_valid: 1>])
[DEBUG: 2025-09-18 11:22:22 : rasterio._io] Jump straight to _read()
[DEBUG: 2025-09-18 11:22:22 : rasterio._io] Window: Window(col_off=0, row_off=0, width=3712, height=3712)
[DEBUG: 2025-09-18 11:22:22 : rasterio._io] IO window xoff=0.0 yoff=0.0 width=3712.0 height=3712.0
[DEBUG: 2025-09-18 11:22:22 : rasterio._io] Output nodata value read from file: None
[DEBUG: 2025-09-18 11:22:22 : rasterio._io] Output nodata values: [None]
[DEBUG: 2025-09-18 11:22:22 : rasterio._io] all_valid: False
[DEBUG: 2025-09-18 11:22:22 : rasterio._io] mask_flags: ([<MaskFlags.per_dataset: 2>, <MaskFlags.alpha: 4>], [<MaskFlags.per_dataset: 2>, <MaskFlags.alpha: 4>], [<MaskFlags.per_dataset: 2>, <MaskFlags.alpha: 4>], [<MaskFlags.all_valid: 1>])
[DEBUG: 2025-09-18 11:22:22 : rasterio._io] Jump straight to _read()
[DEBUG: 2025-09-18 11:22:22 : rasterio._io] Window: Window(col_off=0, row_off=0, width=3712, height=3712)
[DEBUG: 2025-09-18 11:22:22 : rasterio._io] IO window xoff=0.0 yoff=0.0 width=3712.0 height=3712.0

Screenshots

Image

Image

Environment Info:

  • OS: openSUSE Leap 15.6
  • Satpy Version: main

Additional context

I tried to create a custom reader with a standard name, then set this to image_ready, but this just makes the situation worse:

reader:
    name: special-image
    description: reads RGBs from geotiff files
    reader: !!python/name:satpy.readers.core.yaml_reader.FileYAMLReader
    sensors: [world-images]

file_types:
    special-image:
      file_reader: !!python/name:satpy.readers.generic_image.GenericImageFileHandler
      file_patterns:
        - "{name}.tif"

datasets:
  special-image:
    file_type: special-image
    name: special-image
    standard_name: image_ready

Image

What happens here is that trollimage is getting data with floats between 0 and 255, but expects floats between 0 and 1.

As a workaround, this enhancement works (with standard_name: rgb_image):

  rgb_image:
    standard_name: rgb_image
    operations:
      - name: stretch
        method: !!python/name:satpy.enhancements.contrast.stretch
        kwargs:
          stretch: crude
          min_stretch: [0, 0, 0]
          max_stretch: [255, 255, 255]

As a solution, if the GenericImageFileHandler would return integer data, I think satpy wouldn't enhance the data and the round trip load/save should work.

Why am I doing this? I'm creating an RGB world composite by writing each component image to a joint world area, then loading those with a dedicated reader and combining them with the LongitudeMaskingCompositor.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the round trip in the issue using Satpy's generic_image reader and geotiff writer. Inspect how float data from generic_image is enhanced before writing, then verify the chosen behavior against the original and rewritten images. Done means loading and rewriting the GeoTIFF does not visibly change the image.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
data
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.