Skip to content

Commit 4ebcab3

Browse files
Fix standoff transform reading for TransducerArray #380 #381
It was not being converted to a numpy array on read
1 parent 496d395 commit 4ebcab3

6 files changed

Lines changed: 121 additions & 5 deletions

File tree

src/openlifu/db/database.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -851,12 +851,13 @@ def load_system(self, sys_id=None):
851851
sys = UltrasoundSystem.from_file(sys_filename)
852852
return sys
853853

854-
def load_transducer(self, transducer_id, convert_array:bool = True) -> Transducer:
854+
def load_transducer(self, transducer_id, convert_array:bool = True) -> Transducer|TransducerArray:
855855
"""Given a transducer_id, reads the corresponding transducer file from database and returns a transducer object.
856856
Note: the transducer object includes the relative path to the affiliated transducer model data. `get_transducer_absolute_filepaths`, should
857857
be used to obtain the absolute data filepaths based on the Database directory path.
858858
Args:
859859
transducer_id: Transducer ID
860+
convert_array: When enabled, if a TransducerArray is encountered then it is converted to a Transducer.
860861
Returns:
861862
Corresponding Transducer object
862863
"""

src/openlifu/xdc/transducerarray.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ def from_dict(data: dict):
4242
if "type" in d:
4343
d.pop("type")
4444
d["modules"] = [TransformedTransducer.from_dict(t) for t in data["modules"]]
45+
if (
46+
"attrs" in d
47+
and "standoff_transform" in d["attrs"]
48+
and d["attrs"]["standoff_transform"] is not None
49+
):
50+
d["attrs"]["standoff_transform"] = np.array(d["attrs"]["standoff_transform"])
4551
return TransducerArray(**d)
4652

4753

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
{
2+
"type": "TransducerArray",
3+
"id": "example_transducer_array",
4+
"name": "test example of an *array* of *transformed* transducers",
5+
"modules": [
6+
{
7+
"id": "module1",
8+
"name": "Module 1",
9+
"elements": [
10+
{
11+
"index": 1,
12+
"position": [-17.5, 17.5, 0.0],
13+
"orientation": [0.0, 0.0, 0.0],
14+
"size": [3.7, 3.7],
15+
"pin": 1,
16+
"units": "mm"
17+
},
18+
{
19+
"index": 2,
20+
"position": [-17.5, 13.5, 0.0],
21+
"orientation": [0.0, 0.0, 0.0],
22+
"size": [3.7, 3.7],
23+
"pin": 2,
24+
"units": "mm"
25+
}
26+
],
27+
"frequency": 175000.0,
28+
"units": "mm",
29+
"attrs": {},
30+
"registration_surface_filename": null,
31+
"transducer_body_filename": null,
32+
"standoff_transform": [
33+
[1.0, 0.0, 0.0, 0.0],
34+
[0.0, 1.0, 0.0, 0.0],
35+
[0.0, 0.0, 1.0, 0.0],
36+
[0.0, 0.0, 0.0, 1.0]
37+
],
38+
"sensitivity": 1200,
39+
"module_invert": [false],
40+
"transform": [
41+
[0.9, 0.0, -0.2, 22.8],
42+
[0.0, 1.0, 0.0, 0.0],
43+
[0.2, 0.0, 0.9, 3.3],
44+
[0.0, 0.0, 0.0, 1.0]
45+
]
46+
},
47+
{
48+
"id": "module2",
49+
"name": "Module 2",
50+
"elements": [
51+
{
52+
"index": 1,
53+
"position": [-17.5, 17.5, 0.0],
54+
"orientation": [0.0, 0.0, 0.0],
55+
"size": [3.7, 3.7],
56+
"pin": 1,
57+
"units": "mm"
58+
},
59+
{
60+
"index": 2,
61+
"position": [-17.5, 13.5, 0.0],
62+
"orientation": [0.0, 0.0, 0.0],
63+
"size": [3.7, 3.7],
64+
"pin": 2,
65+
"units": "mm"
66+
}
67+
],
68+
"frequency": 180000.0,
69+
"units": "mm",
70+
"attrs": {},
71+
"registration_surface_filename": null,
72+
"transducer_body_filename": null,
73+
"standoff_transform": [
74+
[1.0, 0.0, 0.0, 0.0],
75+
[0.0, 1.0, 0.0, 0.0],
76+
[0.0, 0.0, 1.0, 0.0],
77+
[0.0, 0.0, 0.0, 1.0]
78+
],
79+
"sensitivity": 1000,
80+
"module_invert": [false],
81+
"transform": [
82+
[0.9, 0.0, 0.2, -22.0],
83+
[0.0, 1.0, 0.0, 0.0],
84+
[-0.2, 0.0, 0.9, 4.2],
85+
[0.0, 0.0, 0.0, 1.0]
86+
]
87+
}
88+
],
89+
"attrs": {
90+
"standoff_transform": [
91+
[1.0, 0.0, 0.0, 0.0],
92+
[0.0, 0.9, -0.02, 0.0],
93+
[0.0, 0.02, 0.9, -4.0],
94+
[0.0, 0.0, 0.0, 1.0]
95+
],
96+
"registration_surface_filename": null,
97+
"transducer_body_filename": null
98+
}
99+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{ "transducer_ids": ["example_transducer"] }
1+
{ "transducer_ids": ["example_transducer", "example_transducer_array"] }

tests/test_database.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -666,13 +666,13 @@ def test_session_date_modified_updates_on_write(example_database:Database, examp
666666
assert session.date_modified > initial_modified_time - tolerance
667667

668668
def test_get_transducer_ids(example_database:Database):
669-
assert(example_database.get_transducer_ids() == ["example_transducer"])
669+
assert(example_database.get_transducer_ids() == ["example_transducer", "example_transducer_array"])
670670

671671
def test_write_transducer_nodata(example_database:Database, example_transducer: Transducer):
672672
example_transducer.id = "example_transducer_2"
673673

674674
example_database.write_transducer(example_transducer)
675-
assert(len(example_database.get_transducer_ids()) == 2)
675+
assert(len(example_database.get_transducer_ids()) == 3)
676676
assert("example_transducer" in example_database.get_transducer_ids())
677677
assert("example_transducer_2" in example_database.get_transducer_ids())
678678

tests/test_transducer.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,17 @@
66
import pytest
77
from helpers import dataclasses_are_equal
88

9-
from openlifu.xdc import Element, Transducer
9+
from openlifu.xdc import Element, Transducer, TransducerArray
1010

1111

1212
@pytest.fixture()
1313
def example_transducer() -> Transducer:
1414
return Transducer.from_file(Path(__file__).parent/'resources/example_db/transducers/example_transducer/example_transducer.json')
1515

16+
@pytest.fixture()
17+
def example_transducer_array() -> TransducerArray:
18+
return TransducerArray.from_file(Path(__file__).parent/'resources/example_db/transducers/example_transducer_array/example_transducer_array.json')
19+
1620
@pytest.mark.parametrize("compact_representation", [True, False])
1721
def test_serialize_deserialize_transducer(example_transducer : Transducer, compact_representation: bool):
1822
reconstructed_transducer = example_transducer.from_json(example_transducer.to_json(compact_representation))
@@ -89,3 +93,9 @@ def test_read_data_types(example_transducer:Transducer):
8993
assert isinstance(example_transducer.standoff_transform, np.ndarray)
9094
if len(example_transducer.elements) > 0:
9195
assert isinstance(example_transducer.elements[0], Element)
96+
97+
def test_transducer_array_to_transducer_data_types(example_transducer_array:TransducerArray):
98+
transducer = example_transducer_array.to_transducer()
99+
assert isinstance(transducer.standoff_transform, np.ndarray)
100+
if len(transducer.elements) > 0:
101+
assert isinstance(transducer.elements[0], Element)

0 commit comments

Comments
 (0)