Skip to content

fill_value incompatible with output dtype (stackstac.stack) #260

Open
@ZZMitch

Description

@ZZMitch

Hello,

I recently updated to stackstac 0.5.1 and found a bug/incorrect documentation with stackstac.stack() and the fill_value and dtype parameters. This is related to #250 and tracks back to numpy.can_cast().

Take this example, where I want to grab just the fmask band from HLS L30 over an area at the smallest possible dtype ('unit8'):

Example:

import stackstac as ss

# Temporal bounds
year = 2018
start = str(year) + '-01-01'
end =  str(year) + '-12-31'

# Spatial bounds
bboxLL = (np.float64(-149.53623682903373), np.float64(68.55062861124203), np.float64(-148.30140593046852), np.float64(69.2185427988887))
epsg = 32606
bbox = (np.float64(399535.48481308576), np.float64(7606266.209112197), np.float64(446924.35747663863), np.float64(7679311.477803782))

# STAC settings
gdalEnv = ss.DEFAULT_GDAL_ENV.updated(dict(
    GDAL_DISABLE_READDIR_ON_OPEN = 'TRUE',
    GDAL_HTTP_COOKIEFILE = os.path.expanduser('~/cookies.txt'),
    GDAL_HTTP_COOKIEJAR = os.path.expanduser('~/cookies.txt'),
    GDAL_HTTP_MAX_RETRY = 10,
    GDAL_HTTP_RETRY_DELAY = 15, 
    GDAL_HTTP_UNSAFESSL = 'YES')) # Will pass to Dask cluster workers

catalog = pc.Client.open('https://cmr.earthdata.nasa.gov/stac/LPCLOUD')

# Create stack
items = catalog.search(bbox = bboxLL, datetime = f'{start}/{end}', collections = ['HLSL30.v2.0'], limit = 100).item_collection() 

stack = ss.stack(items, assets = ['Fmask'], epsg = epsg, resolution = 30, bounds = bbox, dtype = 'uint8', fill_value = 255, #np.uint8(255)
    rescale = False, gdal_env = gdalEnv)
stack

The above will fail with:
ValueError: The fill_value 255 is incompatible with the output dtype uint8. Either use dtype='int64', or pick a different fill_value.
Providing another value between 0-255 results in the same error.

Providing a fill_value of np.uint8(255) works and creates a stack with the correct dtype (verified with stack.load():
image

Checking numpy.can_cast(), which the above error points to, we see:

import numpy as np
np.can_cast(type(255), 'uint8') # False
np.can_cast(type(np.uint8(255)), 'uint8') # True

Previously, you could just provide an int like 255. So I am not sure if this is a bug or the documentation for stackstac.stack() needs to be updated to indicate that fill_value should specifically be a numpy dtype.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions