Skip to content

Commit 61ffc38

Browse files
authored
FIX: do not cast _FillValue/missing_value in CFMaskCoder if _Unsigned is provided (#8852)
* FIX: do not cast _FillValue/missing_value in CFMaskCoder if _Unsigned is provided * add whats-new.rst entry * add comment on _Unsigned
1 parent 79272c3 commit 61ffc38

File tree

2 files changed

+14
-3
lines changed

2 files changed

+14
-3
lines changed

doc/whats-new.rst

+3
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ Bug fixes
5757
`CFMaskCoder`/`CFScaleOffsetCoder` (:issue:`2304`, :issue:`5597`,
5858
:issue:`7691`, :pull:`8713`, see also discussion in :pull:`7654`).
5959
By `Kai Mühlbauer <https://github.com/kmuehlbauer>`_.
60+
- do not cast `_FillValue`/`missing_value` in `CFMaskCoder` if `_Unsigned` is provided
61+
(:issue:`8844`, :pull:`8852`).
62+
By `Kai Mühlbauer <https://github.com/kmuehlbauer>`_.
6063

6164
Documentation
6265
~~~~~~~~~~~~~

xarray/coding/variables.py

+11-3
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,9 @@ def encode(self, variable: Variable, name: T_Name = None):
309309
dtype = np.dtype(encoding.get("dtype", data.dtype))
310310
fv = encoding.get("_FillValue")
311311
mv = encoding.get("missing_value")
312+
# to properly handle _FillValue/missing_value below [a], [b]
313+
# we need to check if unsigned data is written as signed data
314+
unsigned = encoding.get("_Unsigned") is not None
312315

313316
fv_exists = fv is not None
314317
mv_exists = mv is not None
@@ -323,13 +326,19 @@ def encode(self, variable: Variable, name: T_Name = None):
323326

324327
if fv_exists:
325328
# Ensure _FillValue is cast to same dtype as data's
326-
encoding["_FillValue"] = dtype.type(fv)
329+
# [a] need to skip this if _Unsigned is available
330+
if not unsigned:
331+
encoding["_FillValue"] = dtype.type(fv)
327332
fill_value = pop_to(encoding, attrs, "_FillValue", name=name)
328333

329334
if mv_exists:
330335
# try to use _FillValue, if it exists to align both values
331336
# or use missing_value and ensure it's cast to same dtype as data's
332-
encoding["missing_value"] = attrs.get("_FillValue", dtype.type(mv))
337+
# [b] need to provide mv verbatim if _Unsigned is available
338+
encoding["missing_value"] = attrs.get(
339+
"_FillValue",
340+
(dtype.type(mv) if not unsigned else mv),
341+
)
333342
fill_value = pop_to(encoding, attrs, "missing_value", name=name)
334343

335344
# apply fillna
@@ -522,7 +531,6 @@ def encode(self, variable: Variable, name: T_Name = None) -> Variable:
522531
def decode(self, variable: Variable, name: T_Name = None) -> Variable:
523532
if "_Unsigned" in variable.attrs:
524533
dims, data, attrs, encoding = unpack_for_decoding(variable)
525-
526534
unsigned = pop_to(attrs, encoding, "_Unsigned")
527535

528536
if data.dtype.kind == "i":

0 commit comments

Comments
 (0)