Repository: European-XFEL/EXtra-data

Issue:
stack_detector_data has wrong default fill value for uint64 data
We've assumed that `np.nan` is universally converted to 0 for integer dtypes, but that doesn't hold for uint64:

```
In [4]: np.full(1, np.nan, dtype=np.uint32)                            
Out[4]: array([0], dtype=uint32)

In [5]: np.full(1, np.nan, dtype=np.uint64)                            
Out[5]: array([9223372036854775808], dtype=uint64)
```

Karim noticed that `stack_detector_data` was giving different results for missing pulseId (uint64) than missing cellId (uint16). We have documented it as filling with 0 by default for integers.

Discussion:

Patch:
diff --git a/extra_data/stacking.py b/extra_data/stacking.py
index 7b5f29e..a4878f6 100644
--- a/extra_data/stacking.py
+++ b/extra_data/stacking.py
@@ -53,7 +53,7 @@ def stack_data(train, data, axis=-3, xcept=()):
     return np.stack(ordered_arrays, axis=axis)
 
 
-def stack_detector_data(train, data, axis=-3, modules=16, fillvalue=np.nan,
+def stack_detector_data(train, data, axis=-3, modules=16, fillvalue=None,
                         real_array=True):
     """Stack data from detector modules in a train.
 
@@ -117,6 +117,11 @@ def stack_detector_data(train, data, axis=-3, modules=16, fillvalue=np.nan,
 
     dtype = dtypes.pop()
     shape = shapes.pop()
+
+    if fillvalue is None:
+        fillvalue = np.nan if dtype.kind == 'f' else 0
+    fillvalue = dtype.type(fillvalue)  # check value compatibility with dtype
+
     stack = StackView(
         modno_arrays, modules, shape, dtype, fillvalue, stack_axis=axis
     )


Test patch:
diff --git a/extra_data/tests/test_stacking.py b/extra_data/tests/test_stacking.py
index 08dead6..3492c59 100644
--- a/extra_data/tests/test_stacking.py
+++ b/extra_data/tests/test_stacking.py
@@ -42,6 +42,13 @@ def test_stack_detector_data_missing(mock_fxe_raw_run):
     assert (comb[:, :, 7] == 22).all()  # Key missing
     assert (comb[:, :, 5] == 22).all()  # Empty array
 
+    # default fillvalue for int is 0
+    comb = stack_detector_data(data, 'image.data')
+    assert (comb[:, :, 3] == 0).all()
+
+    with pytest.raises(ValueError):
+        comb = stack_detector_data(data, 'image.data', fillvalue=np.nan)
+
 
 def test_stack_detector_data_stackview(mock_fxe_raw_run):
     test_run = RunDirectory(mock_fxe_raw_run)