Skip to content

Commit 2753fc9

Browse files
Build array conversion into DictMixin (OpenwaterHealth#119)
This is just a convenience so when we add new numpy array fields to dataclasses we don't have to manually build the numpy array conversion into the `from_dict` of the class
1 parent 9d3acf7 commit 2753fc9

3 files changed

Lines changed: 20 additions & 9 deletions

File tree

src/openlifu/db/session.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,13 +138,13 @@ def from_dict(d:Dict):
138138
if 'volume' in d:
139139
raise ValueError("Sessions no longer recognize a volume attribute -- it is now volume_id.")
140140
if 'array_transform' in d:
141-
d['array_transform'] = ArrayTransform(np.array(d['array_transform']['matrix']), d['array_transform']['units'])
141+
d['array_transform'] = ArrayTransform.from_dict(d['array_transform'])
142142
if 'transducer_tracking_results' in d:
143143
d['transducer_tracking_results'] = [
144144
TransducerTrackingResult(
145145
t['photoscan_id'],
146-
ArrayTransform(np.array(t['transducer_to_photoscan_transform']['matrix']),t['transducer_to_photoscan_transform']['units']),
147-
ArrayTransform(np.array(t['photoscan_to_volume_transform']['matrix']), t['photoscan_to_volume_transform']['units']),
146+
ArrayTransform.from_dict(t['transducer_to_photoscan_transform']),
147+
ArrayTransform.from_dict(t['photoscan_to_volume_transform']),
148148
t['transducer_to_photoscan_tracking_approved'],
149149
t['photoscan_to_volume_tracking_approved']
150150
)
@@ -161,7 +161,7 @@ def from_dict(d:Dict):
161161
for target_id,(approval,transforms) in d['virtual_fit_results'].items():
162162
d['virtual_fit_results'][target_id] = (
163163
approval,
164-
[ArrayTransform(np.array(t_dict["matrix"]), t_dict["units"]) for t_dict in transforms],
164+
[ArrayTransform.from_dict(t_dict) for t_dict in transforms],
165165
)
166166
if isinstance(d['markers'], list):
167167
if len(d['markers'])>0 and isinstance(d['markers'][0], dict):

src/openlifu/geo.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import numpy as np
99
import vtk
1010

11+
from openlifu.util.dict_conversion import DictMixin
1112
from openlifu.util.units import getunitconversion
1213

1314

@@ -140,7 +141,7 @@ def to_json(self, compact:bool) -> str:
140141

141142

142143
@dataclass
143-
class ArrayTransform:
144+
class ArrayTransform(DictMixin):
144145
"""An affine transform with a unit string, often intended to represent how a transducer array is positionsed in space."""
145146

146147
matrix: np.ndarray

src/openlifu/util/dict_conversion.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
from __future__ import annotations
22

3-
from dataclasses import asdict, dataclass
4-
from typing import Any, Dict, Type, TypeVar
3+
from dataclasses import asdict, dataclass, fields
4+
from typing import Any, Dict, Type, TypeVar, get_origin
5+
6+
import numpy as np
57

68
T = TypeVar('T', bound='DictMixin')
79

810
@dataclass
911
class DictMixin:
10-
"""Mixin for basic conversion to and from dict."""
12+
"""Mixin for basic conversion of a dataclass to and from dict."""
1113
def to_dict(self) -> Dict[str,Any]:
1214
"""
1315
Convert the object to a dictionary
@@ -27,4 +29,12 @@ def from_dict(cls : Type[T], parameter_dict:Dict[str,Any]) -> T:
2729
"""
2830
if "class" in parameter_dict:
2931
parameter_dict.pop("class")
30-
return cls(**parameter_dict)
32+
new_object = cls(**parameter_dict)
33+
34+
# Convert anything that should be a numpy array to numpy
35+
for field in fields(cls):
36+
# Note that sometimes "field.type" is a string rather than a type due to the "from annotations import __future__" stuff
37+
if get_origin(field.type) is np.ndarray or field.type is np.ndarray or "np.ndarray" in field.type:
38+
setattr(new_object, field.name, np.array(getattr(new_object,field.name)))
39+
40+
return new_object

0 commit comments

Comments
 (0)