Skip to content

Commit 5d10c5b

Browse files
authored
Merge pull request #1341 from effigies/typ/fix-otp
RF: Replace OneTimeProperty/auto_attr with cached_property
2 parents beb4f7b + b6eccc2 commit 5d10c5b

File tree

4 files changed

+77
-127
lines changed

4 files changed

+77
-127
lines changed

doc/tools/build_modref_templates.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import sys
1010

1111
# version comparison
12-
from distutils.version import LooseVersion as V
12+
from packaging.version import Version as V
1313
from os.path import join as pjoin
1414

1515
# local imports
@@ -73,6 +73,8 @@ def abort(error):
7373
if re.match('^_version_(major|minor|micro|extra)', v)
7474
]
7575
)
76+
77+
source_version = V(source_version)
7678
print('***', source_version)
7779

7880
if source_version != installed_version:

nibabel/nicom/dicomwrappers.py

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@
1414

1515
import operator
1616
import warnings
17+
from functools import cached_property
1718

1819
import numpy as np
1920

2021
from nibabel.optpkg import optional_package
2122

22-
from ..onetime import auto_attr as one_time
2323
from ..openers import ImageOpener
2424
from . import csareader as csar
2525
from .dwiparams import B2q, nearest_pos_semi_def, q2bg
@@ -140,15 +140,15 @@ def __init__(self, dcm_data):
140140
"""
141141
self.dcm_data = dcm_data
142142

143-
@one_time
143+
@cached_property
144144
def image_shape(self):
145145
"""The array shape as it will be returned by ``get_data()``"""
146146
shape = (self.get('Rows'), self.get('Columns'))
147147
if None in shape:
148148
return None
149149
return shape
150150

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

161-
@one_time
161+
@cached_property
162162
def slice_normal(self):
163163
iop = self.image_orient_patient
164164
if iop is None:
165165
return None
166166
# iop[:, 0] is column index cosine, iop[:, 1] is row index cosine
167167
return np.cross(iop[:, 1], iop[:, 0])
168168

169-
@one_time
169+
@cached_property
170170
def rotation_matrix(self):
171171
"""Return rotation matrix between array indices and mm
172172
@@ -193,7 +193,7 @@ def rotation_matrix(self):
193193
raise WrapperPrecisionError('Rotation matrix not nearly orthogonal')
194194
return R
195195

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

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

234-
@one_time
234+
@cached_property
235235
def slice_indicator(self):
236236
"""A number that is higher for higher slices in Z
237237
@@ -246,12 +246,12 @@ def slice_indicator(self):
246246
return None
247247
return np.inner(ipp, s_norm)
248248

249-
@one_time
249+
@cached_property
250250
def instance_number(self):
251251
"""Just because we use this a lot for sorting"""
252252
return self.get('InstanceNumber')
253253

254-
@one_time
254+
@cached_property
255255
def series_signature(self):
256256
"""Signature for matching slices into series
257257
@@ -390,15 +390,15 @@ def _apply_scale_offset(self, data, scale, offset):
390390
return data + offset
391391
return data
392392

393-
@one_time
393+
@cached_property
394394
def b_value(self):
395395
"""Return b value for diffusion or None if not available"""
396396
q_vec = self.q_vector
397397
if q_vec is None:
398398
return None
399399
return q2bg(q_vec)[0]
400400

401-
@one_time
401+
@cached_property
402402
def b_vector(self):
403403
"""Return b vector for diffusion or None if not available"""
404404
q_vec = self.q_vector
@@ -469,7 +469,7 @@ def __init__(self, dcm_data):
469469
raise WrapperError('SharedFunctionalGroupsSequence is empty.')
470470
self._shape = None
471471

472-
@one_time
472+
@cached_property
473473
def image_shape(self):
474474
"""The array shape as it will be returned by ``get_data()``
475475
@@ -573,7 +573,7 @@ def image_shape(self):
573573
)
574574
return tuple(shape)
575575

576-
@one_time
576+
@cached_property
577577
def image_orient_patient(self):
578578
"""
579579
Note that this is _not_ LR flipped
@@ -590,7 +590,7 @@ def image_orient_patient(self):
590590
iop = np.array(list(map(float, iop)))
591591
return np.array(iop).reshape(2, 3).T
592592

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

613-
@one_time
613+
@cached_property
614614
def image_position(self):
615615
try:
616616
ipp = self.shared.PlanePositionSequence[0].ImagePositionPatient
@@ -623,7 +623,7 @@ def image_position(self):
623623
return None
624624
return np.array(list(map(float, ipp)))
625625

626-
@one_time
626+
@cached_property
627627
def series_signature(self):
628628
signature = {}
629629
eq = operator.eq
@@ -696,7 +696,7 @@ def __init__(self, dcm_data, csa_header=None):
696696
csa_header = {}
697697
self.csa_header = csa_header
698698

699-
@one_time
699+
@cached_property
700700
def slice_normal(self):
701701
# The std_slice_normal comes from the cross product of the directions
702702
# in the ImageOrientationPatient
@@ -720,7 +720,7 @@ def slice_normal(self):
720720
else:
721721
return std_slice_normal
722722

723-
@one_time
723+
@cached_property
724724
def series_signature(self):
725725
"""Add ICE dims from CSA header to signature"""
726726
signature = super().series_signature
@@ -730,7 +730,7 @@ def series_signature(self):
730730
signature['ICE_Dims'] = (ice, operator.eq)
731731
return signature
732732

733-
@one_time
733+
@cached_property
734734
def b_matrix(self):
735735
"""Get DWI B matrix referring to voxel space
736736
@@ -767,7 +767,7 @@ def b_matrix(self):
767767
# semi-definite.
768768
return nearest_pos_semi_def(B_vox)
769769

770-
@one_time
770+
@cached_property
771771
def q_vector(self):
772772
"""Get DWI q vector referring to voxel space
773773
@@ -840,7 +840,7 @@ def __init__(self, dcm_data, csa_header=None, n_mosaic=None):
840840
self.n_mosaic = n_mosaic
841841
self.mosaic_size = int(np.ceil(np.sqrt(n_mosaic)))
842842

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

853-
@one_time
853+
@cached_property
854854
def image_position(self):
855855
"""Return position of first voxel in data block
856856

0 commit comments

Comments
 (0)