Source code for fileformats.medimage.diffusion

import typing

from fileformats.core import extra, validated_property
from fileformats.core.mixin import WithAdjacentFiles
from fileformats.core.typing import TypeAlias
from fileformats.generic import BinaryFile

from .nifti import Nifti1, NiftiGz, NiftiGzX, NiftiX

if typing.TYPE_CHECKING:
    import numpy.typing  # noqa: F401

EncodingArrayType: TypeAlias = (
    typing.Any
)  # In Py<3.9 this is problematic "numpy.typing.NDArray[numpy.floating[typing.Any]]"


[docs] class DwiEncoding:
[docs] @extra def read_encodings(self) -> EncodingArrayType: "Both the gradient direction and weighting combined into a single Nx4 array" raise NotImplementedError
@property def encodings_array(self) -> EncodingArrayType: return self.read_encodings() @property def directions(self) -> EncodingArrayType: "gradient direction and weighting combined into a single Nx4 array" return self.encodings_array[:, :3] @property def b_values(self) -> EncodingArrayType: "the b-value weighting" return self.encodings_array[:, 3]
[docs] class Bval(BinaryFile): ext = ".bval" @extra def read_array(self) -> EncodingArrayType: raise NotImplementedError
[docs] class Bvec(WithAdjacentFiles, DwiEncoding, BinaryFile): """FSL-style diffusion encoding, in two separate files""" ext = ".bvec" @validated_property def b_values_file(self) -> Bval: return Bval(self.select_by_ext(Bval)) @validated_property def num_encodings(self) -> int: num_bvals = len(self.b_values_file.read_contents().split()) x_len, y_len, z_len = [ len(ln.split()) for ln in self.read_contents().splitlines() ] if not (x_len == y_len == z_len): raise ValueError( "The number of entries in each bvec component must match" f"x_len={x_len}, y_len={y_len}, z_len={z_len}" ) num_bvecs = x_len if num_bvals != num_bvecs: raise ValueError( f"The number of b-values ({num_bvals}) does not match the number of " f"directions {num_bvecs}" ) return num_bvals
# NIfTI file format gzipped with BIDS side car class WithBvec(WithAdjacentFiles): @validated_property def encoding(self) -> Bvec: return Bvec(self.select_by_ext(Bvec)) # type: ignore[attr-defined]
[docs] class NiftiBvec(WithBvec, Nifti1): iana_mime = "application/x-nifti2+bvec"
[docs] class NiftiGzBvec(WithBvec, NiftiGz): iana_mime = "application/x-nifti2+gzip.bvec"
[docs] class NiftiXBvec(WithBvec, NiftiX): iana_mime = "application/x-nifti2+json.bvec"
[docs] class NiftiGzXBvec(WithBvec, NiftiGzX): iana_mime = "application/x-nifti2+gzip.json.bvec"