Skip to content

Commit 99215b2

Browse files
committed
Added test for the '_parse_metadata' function
1 parent 3ca97cd commit 99215b2

1 file changed

Lines changed: 256 additions & 3 deletions

File tree

tests/workflows/fib/test_register_atlas.py

Lines changed: 256 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1+
import xml.etree.ElementTree as ET
12
from pathlib import Path
3+
from unittest.mock import MagicMock
24

35
import pytest
46
from pytest_mock import MockerFixture
57
from sqlmodel import Session, select
68

79
import murfey.util.db as MurfeyDB
8-
from murfey.workflows.fib.register_atlas import FIBAtlasMetadata, run
10+
from murfey.workflows.fib.register_atlas import FIBAtlasMetadata, _parse_metadata, run
911

1012
session_id = 10
1113
visit_name = "cm12345-6"
@@ -19,8 +21,259 @@ def visit_dir(tmp_path: Path):
1921
return visit_dir
2022

2123

22-
def test_parse_metadata():
23-
pass
24+
def create_electron_snapshot_metadata(
25+
voltage: float,
26+
shift_x: float,
27+
shift_y: float,
28+
len_x: float,
29+
len_y: float,
30+
pos_x: float,
31+
pos_y: float,
32+
pos_z: float,
33+
rotation: float,
34+
tilt_alpha: float,
35+
tilt_beta: float,
36+
pixels_x: int,
37+
pixels_y: int,
38+
pixel_size_x: float,
39+
pixel_size_y: float,
40+
):
41+
# Create the XML Element structure present in the file
42+
root = ET.Element("Metadata")
43+
44+
# ------
45+
# Optics
46+
# ------
47+
optics_node = ET.Element("Optics")
48+
49+
voltage_node = ET.Element("AccelerationVoltage")
50+
voltage_node.text = str(voltage)
51+
optics_node.append(voltage_node)
52+
53+
beam_shift_node = ET.Element("BeamShift")
54+
shift_x_node = ET.Element("X")
55+
shift_x_node.text = str(shift_x)
56+
beam_shift_node.append(shift_x_node)
57+
shift_y_node = ET.Element("Y")
58+
shift_y_node.text = str(shift_y)
59+
beam_shift_node.append(shift_y_node)
60+
optics_node.append(beam_shift_node)
61+
62+
fov_node = ET.Element("ScanFieldOfView")
63+
len_x_node = ET.Element("X")
64+
len_x_node.text = str(len_x)
65+
fov_node.append(len_x_node)
66+
len_y_node = ET.Element("Y")
67+
len_y_node.text = str(len_y)
68+
fov_node.append(len_y_node)
69+
optics_node.append(fov_node)
70+
71+
root.append(optics_node)
72+
73+
# -------------
74+
# StageSettings
75+
# -------------
76+
stage_settings_node = ET.Element("StageSettings")
77+
# x, y, z
78+
stage_node = ET.Element("StagePosition")
79+
pos_x_node = ET.Element("X")
80+
pos_x_node.text = str(pos_x)
81+
stage_node.append(pos_x_node)
82+
pos_y_node = ET.Element("Y")
83+
pos_y_node.text = str(pos_y)
84+
stage_node.append(pos_y_node)
85+
pos_z_node = ET.Element("Z")
86+
pos_z_node.text = str(pos_z)
87+
stage_node.append(pos_z_node)
88+
rotation_node = ET.Element("Rotation")
89+
rotation_node.text = str(rotation)
90+
stage_node.append(rotation_node)
91+
# Angles
92+
tilt_node = ET.Element("Tilt")
93+
tilt_alpha_node = ET.Element("Alpha")
94+
tilt_alpha_node.text = str(tilt_alpha)
95+
tilt_node.append(tilt_alpha_node)
96+
tilt_beta_node = ET.Element("Beta")
97+
tilt_beta_node.text = str(tilt_beta)
98+
tilt_node.append(tilt_beta_node)
99+
stage_node.append(tilt_node)
100+
101+
stage_settings_node.append(stage_node)
102+
root.append(stage_settings_node)
103+
104+
# ------------
105+
# BinaryResult
106+
# ------------
107+
binary_result_node = ET.Element("BinaryResult")
108+
# ImageSize
109+
image_size_node = ET.Element("ImageSize")
110+
pixels_x_node = ET.Element("X")
111+
pixels_x_node.text = str(pixels_x)
112+
image_size_node.append(pixels_x_node)
113+
pixels_y_node = ET.Element("Y")
114+
pixels_y_node.text = str(pixels_y)
115+
image_size_node.append(pixels_y_node)
116+
binary_result_node.append(image_size_node)
117+
# PixelSize
118+
pixel_size_node = ET.Element("PixelSize")
119+
pixel_size_x_node = ET.Element("X")
120+
pixel_size_x_node.text = str(pixel_size_x)
121+
pixel_size_node.append(pixel_size_x_node)
122+
pixel_size_y_node = ET.Element("Y")
123+
pixel_size_y_node.text = str(pixel_size_y)
124+
pixel_size_node.append(pixel_size_y_node)
125+
binary_result_node.append(pixel_size_node)
126+
127+
root.append(binary_result_node)
128+
129+
xml_string = ET.tostring(root, encoding="unicode", xml_declaration=True)
130+
return xml_string
131+
132+
133+
@pytest.mark.parametrize(
134+
"test_params",
135+
(
136+
(
137+
"Electron Snapshot",
138+
"some_project",
139+
2000, # Voltage
140+
0, # Beam shift X
141+
0, # Y
142+
0.003072, # Field of view X
143+
0.002048, # Y
144+
0.003, # Stage X
145+
0.0003, # Y
146+
0.01, # Z
147+
-1.309, # Rotation
148+
0.8, # Alpha tilt
149+
0, # Beta tilt
150+
3072, # Image size X
151+
2048, # Y
152+
1e-6, # Pixel size X
153+
1e-6, # Y
154+
),
155+
(
156+
"Electron Snapshot (2)",
157+
"another_project",
158+
2000, # Voltage
159+
0, # Beam shift X
160+
0, # Y
161+
0.003072, # Field of view X
162+
0.002048, # Y
163+
-0.003, # Stage X
164+
0.0003, # Y
165+
0.01, # Z
166+
1.309, # Rotation
167+
0, # Alpha tilt
168+
0, # Beta tilt
169+
3072, # Image size X
170+
2048, # Y
171+
1e-6, # Pixel size X
172+
1e-6, # Y
173+
),
174+
),
175+
)
176+
def test_parse_metadata(
177+
mocker: MockerFixture,
178+
test_params: tuple[
179+
str,
180+
str,
181+
float,
182+
float,
183+
float,
184+
float,
185+
float,
186+
float,
187+
float,
188+
float,
189+
float,
190+
float,
191+
float,
192+
int,
193+
int,
194+
float,
195+
float,
196+
],
197+
visit_dir: Path,
198+
):
199+
# Unpack test params
200+
(
201+
image_name,
202+
project_name,
203+
voltage,
204+
shift_x,
205+
shift_y,
206+
len_x,
207+
len_y,
208+
pos_x,
209+
pos_y,
210+
pos_z,
211+
rotation,
212+
tilt_alpha,
213+
tilt_beta,
214+
pixels_x,
215+
pixels_y,
216+
pixel_size_x,
217+
pixel_size_y,
218+
) = test_params
219+
file = (
220+
visit_dir
221+
/ "maps"
222+
/ project_name
223+
/ "LayersData/Layer"
224+
/ image_name
225+
/ f"{image_name}.tiff"
226+
)
227+
slot_number = 1 if pos_x < 0 else 2
228+
229+
# Mock the results of opening an image file
230+
xml_string = create_electron_snapshot_metadata(
231+
voltage,
232+
shift_x,
233+
shift_y,
234+
len_x,
235+
len_y,
236+
pos_x,
237+
pos_y,
238+
pos_z,
239+
rotation,
240+
tilt_alpha,
241+
tilt_beta,
242+
pixels_x,
243+
pixels_y,
244+
pixel_size_x,
245+
pixel_size_y,
246+
)
247+
mock_image = MagicMock()
248+
mock_image.tag_v2 = {34683: xml_string}
249+
mocker.patch(
250+
"murfey.workflows.fib.register_atlas.PIL.Image.open",
251+
return_value=mock_image,
252+
)
253+
254+
# Run the function and check that output is correct
255+
parsed = _parse_metadata(file, visit_name)
256+
257+
assert parsed.visit_name == visit_name
258+
assert parsed.file == file
259+
assert parsed.voltage == voltage
260+
assert parsed.shift_x == shift_x
261+
assert parsed.shift_y == shift_y
262+
assert parsed.len_x == len_x
263+
assert parsed.len_y == len_y
264+
assert parsed.pos_x == pos_x
265+
assert parsed.pos_y == pos_y
266+
assert parsed.pos_z == pos_z
267+
assert parsed.rotation == rotation
268+
assert parsed.tilt_alpha == tilt_alpha
269+
assert parsed.tilt_beta == tilt_beta
270+
assert parsed.pixels_x == pixels_x
271+
assert parsed.pixels_y == pixels_y
272+
assert parsed.pixel_size_x == pixel_size_x
273+
assert parsed.pixel_size_y == pixel_size_y
274+
assert parsed.slot_number == slot_number
275+
assert parsed.site_name == f"{project_name}--slot_{slot_number}"
276+
assert parsed.pixel_size == 0.5 * (pixel_size_x + pixel_size_y)
24277

25278

26279
def test_register_fib_imaging_site():

0 commit comments

Comments
 (0)