class NrrdReader(base.ImageReader):
def __init__(
self,
output: Literal["voxels", "dotprops", "raw"] = "voxels",
threshold: Optional[Union[int, float]] = None,
thin: bool = False,
dotprop_kwargs: Dict[str, Any] = {},
fmt: str = DEFAULT_FMT,
attrs: Optional[Dict[str, Any]] = None,
errors: str = "raise",
):
if not fmt.endswith(".nrrd"):
raise ValueError('`fmt` must end with ".nrrd"')
super().__init__(
fmt=fmt,
attrs=attrs,
file_ext=".nrrd",
name_fallback="NRRD",
read_binary=True,
output=output,
threshold=threshold,
thin=thin,
dotprop_kwargs=dotprop_kwargs,
errors=errors,
)
def format_output(self, x):
# This function replaces the BaseReader.format_output()
# This is to avoid trying to convert multiple (image, header) to NeuronList
if self.output == "raw":
return [n for n in x if n]
elif x:
return core.NeuronList([n for n in x if n])
else:
return core.NeuronList([])
@base.handle_errors
def read_buffer(
self, f, attrs: Optional[Dict[str, Any]] = None
) -> Union[np.ndarray, "core.Dotprops", "core.VoxelNeuron"]:
"""Read buffer into (image, header) or a neuron.
Parameters
----------
f : IO
Readable buffer (must be bytes).
attrs : dict | None
Arbitrary attributes to include in the neuron.
Returns
-------
core.Dotprops | core.VoxelNeuron | np.ndarray
"""
if isinstance(f, HTTPResponse):
f = io.StringIO(f.content)
if isinstance(f, bytes):
f = io.BytesIO(f)
header = nrrd.read_header(f)
data = nrrd.read_data(header, f)
if self.output == "raw":
return data, header
# Try parsing units - this is modelled after the nrrd files you get from
# Virtual Fly Brain (VFB)
units = None
space_units = None
voxdim = np.array([1, 1, 1])
if "space directions" in header:
sd = np.asarray(header["space directions"])
if sd.ndim == 2:
voxdim = np.diag(sd)[:3]
if "space units" in header:
space_units = header["space units"]
if len(space_units) == 3:
units = [f"{m} {u}" for m, u in zip(voxdim, space_units)]
else:
units = voxdim
return self.convert_image(data, attrs, header, voxdim, units, space_units)