Skip to content

Commit

Permalink
Merge pull request #1341 from effigies/typ/fix-otp
Browse files Browse the repository at this point in the history
RF: Replace OneTimeProperty/auto_attr with cached_property
  • Loading branch information
effigies authored Jul 26, 2024
2 parents beb4f7b + b6eccc2 commit 5d10c5b
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 127 deletions.
4 changes: 3 additions & 1 deletion doc/tools/build_modref_templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import sys

# version comparison
from distutils.version import LooseVersion as V
from packaging.version import Version as V
from os.path import join as pjoin

# local imports
Expand Down Expand Up @@ -73,6 +73,8 @@ def abort(error):
if re.match('^_version_(major|minor|micro|extra)', v)
]
)

source_version = V(source_version)
print('***', source_version)

if source_version != installed_version:
Expand Down
46 changes: 23 additions & 23 deletions nibabel/nicom/dicomwrappers.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@

import operator
import warnings
from functools import cached_property

import numpy as np

from nibabel.optpkg import optional_package

from ..onetime import auto_attr as one_time
from ..openers import ImageOpener
from . import csareader as csar
from .dwiparams import B2q, nearest_pos_semi_def, q2bg
Expand Down Expand Up @@ -140,15 +140,15 @@ def __init__(self, dcm_data):
"""
self.dcm_data = dcm_data

@one_time
@cached_property
def image_shape(self):
"""The array shape as it will be returned by ``get_data()``"""
shape = (self.get('Rows'), self.get('Columns'))
if None in shape:
return None
return shape

@one_time
@cached_property
def image_orient_patient(self):
"""Note that this is _not_ LR flipped"""
iop = self.get('ImageOrientationPatient')
Expand All @@ -158,15 +158,15 @@ def image_orient_patient(self):
iop = np.array(list(map(float, iop)))
return np.array(iop).reshape(2, 3).T

@one_time
@cached_property
def slice_normal(self):
iop = self.image_orient_patient
if iop is None:
return None
# iop[:, 0] is column index cosine, iop[:, 1] is row index cosine
return np.cross(iop[:, 1], iop[:, 0])

@one_time
@cached_property
def rotation_matrix(self):
"""Return rotation matrix between array indices and mm
Expand All @@ -193,7 +193,7 @@ def rotation_matrix(self):
raise WrapperPrecisionError('Rotation matrix not nearly orthogonal')
return R

@one_time
@cached_property
def voxel_sizes(self):
"""voxel sizes for array as returned by ``get_data()``"""
# pix space gives (row_spacing, column_spacing). That is, the
Expand All @@ -212,7 +212,7 @@ def voxel_sizes(self):
pix_space = list(map(float, pix_space))
return tuple(pix_space + [zs])

@one_time
@cached_property
def image_position(self):
"""Return position of first voxel in data block
Expand All @@ -231,7 +231,7 @@ def image_position(self):
# Values are python Decimals in pydicom 0.9.7
return np.array(list(map(float, ipp)))

@one_time
@cached_property
def slice_indicator(self):
"""A number that is higher for higher slices in Z
Expand All @@ -246,12 +246,12 @@ def slice_indicator(self):
return None
return np.inner(ipp, s_norm)

@one_time
@cached_property
def instance_number(self):
"""Just because we use this a lot for sorting"""
return self.get('InstanceNumber')

@one_time
@cached_property
def series_signature(self):
"""Signature for matching slices into series
Expand Down Expand Up @@ -390,15 +390,15 @@ def _apply_scale_offset(self, data, scale, offset):
return data + offset
return data

@one_time
@cached_property
def b_value(self):
"""Return b value for diffusion or None if not available"""
q_vec = self.q_vector
if q_vec is None:
return None
return q2bg(q_vec)[0]

@one_time
@cached_property
def b_vector(self):
"""Return b vector for diffusion or None if not available"""
q_vec = self.q_vector
Expand Down Expand Up @@ -469,7 +469,7 @@ def __init__(self, dcm_data):
raise WrapperError('SharedFunctionalGroupsSequence is empty.')
self._shape = None

@one_time
@cached_property
def image_shape(self):
"""The array shape as it will be returned by ``get_data()``
Expand Down Expand Up @@ -573,7 +573,7 @@ def image_shape(self):
)
return tuple(shape)

@one_time
@cached_property
def image_orient_patient(self):
"""
Note that this is _not_ LR flipped
Expand All @@ -590,7 +590,7 @@ def image_orient_patient(self):
iop = np.array(list(map(float, iop)))
return np.array(iop).reshape(2, 3).T

@one_time
@cached_property
def voxel_sizes(self):
"""Get i, j, k voxel sizes"""
try:
Expand All @@ -610,7 +610,7 @@ def voxel_sizes(self):
# Ensure values are float rather than Decimal
return tuple(map(float, list(pix_space) + [zs]))

@one_time
@cached_property
def image_position(self):
try:
ipp = self.shared.PlanePositionSequence[0].ImagePositionPatient
Expand All @@ -623,7 +623,7 @@ def image_position(self):
return None
return np.array(list(map(float, ipp)))

@one_time
@cached_property
def series_signature(self):
signature = {}
eq = operator.eq
Expand Down Expand Up @@ -696,7 +696,7 @@ def __init__(self, dcm_data, csa_header=None):
csa_header = {}
self.csa_header = csa_header

@one_time
@cached_property
def slice_normal(self):
# The std_slice_normal comes from the cross product of the directions
# in the ImageOrientationPatient
Expand All @@ -720,7 +720,7 @@ def slice_normal(self):
else:
return std_slice_normal

@one_time
@cached_property
def series_signature(self):
"""Add ICE dims from CSA header to signature"""
signature = super().series_signature
Expand All @@ -730,7 +730,7 @@ def series_signature(self):
signature['ICE_Dims'] = (ice, operator.eq)
return signature

@one_time
@cached_property
def b_matrix(self):
"""Get DWI B matrix referring to voxel space
Expand Down Expand Up @@ -767,7 +767,7 @@ def b_matrix(self):
# semi-definite.
return nearest_pos_semi_def(B_vox)

@one_time
@cached_property
def q_vector(self):
"""Get DWI q vector referring to voxel space
Expand Down Expand Up @@ -840,7 +840,7 @@ def __init__(self, dcm_data, csa_header=None, n_mosaic=None):
self.n_mosaic = n_mosaic
self.mosaic_size = int(np.ceil(np.sqrt(n_mosaic)))

@one_time
@cached_property
def image_shape(self):
"""Return image shape as returned by ``get_data()``"""
# reshape pixel slice array back from mosaic
Expand All @@ -850,7 +850,7 @@ def image_shape(self):
return None
return (rows // self.mosaic_size, cols // self.mosaic_size, self.n_mosaic)

@one_time
@cached_property
def image_position(self):
"""Return position of first voxel in data block
Expand Down
Loading

0 comments on commit 5d10c5b

Please sign in to comment.