split node tests into standalone files

This commit is contained in:
2026-03-29 16:39:37 -07:00
parent 7983736c2e
commit c3bb34d248
53 changed files with 2625 additions and 0 deletions

View File

@@ -0,0 +1,138 @@
import json
import os
import tempfile
from pathlib import Path
import numpy as np
import tifffile
from PIL import Image as PILImage
from backend.data_types import DataField, ImageData, LineData, RecordTable, MeshModel, DataTable
def test_save_generic():
from backend.nodes.save import Save
node = Save()
value_spec = node.INPUT_TYPES()["required"]["value"]
assert value_spec[0] == "DATA_FIELD"
assert value_spec[1]["accepted_types"] == [
"IMAGE", "ANNOTATION_SOURCE", "LINE", "RECORD_TABLE", "DATA_TABLE", "MESH_MODEL", "FLOAT",
]
format_choices = node.INPUT_TYPES()["required"]["format"][1]["choices_by_source_type"]
assert format_choices["ANNOTATION_SOURCE"] == format_choices["IMAGE"]
with tempfile.TemporaryDirectory() as tmpdir:
node.save(filename="scalar", directory_path=tmpdir, format="TXT", value=3.5)
assert Path(tmpdir, "scalar.txt").read_text(encoding="utf-8").strip() == "3.5"
node.save(filename="scalar_json", directory_path=tmpdir, format="JSON", value=3.5)
assert json.loads(Path(tmpdir, "scalar_json.json").read_text(encoding="utf-8")) == {"value": 3.5}
line = LineData(data=np.array([1.0, 2.0, 3.0]), x_axis=np.array([0.0, 0.5, 1.0]), x_unit="um", y_unit="nm")
node.save(filename="profile", directory_path=tmpdir, format="CSV", value=line)
csv_text = Path(tmpdir, "profile.csv").read_text(encoding="utf-8")
assert "x,y,x_unit,y_unit" in csv_text
assert "um" in csv_text and "nm" in csv_text
node.save(filename="profile_npz", directory_path=tmpdir, format="NPZ", value=line)
line_npz = np.load(Path(tmpdir, "profile_npz.npz"))
assert np.allclose(line_npz["x"], line.x_axis)
assert np.allclose(line_npz["y"], line.data)
node.save(filename="profile_json", directory_path=tmpdir, format="JSON", value=line)
line_json = json.loads(Path(tmpdir, "profile_json.json").read_text(encoding="utf-8"))
assert line_json["x_unit"] == "um"
assert line_json["y_unit"] == "nm"
assert line_json["x"] == [0.0, 0.5, 1.0]
assert line_json["y"] == [1.0, 2.0, 3.0]
field = DataField(
data=np.array([[1.0, 2.0], [3.0, 4.5]], dtype=np.float64),
xreal=2e-6, yreal=1e-6, si_unit_xy="m", si_unit_z="m", colormap="viridis",
)
node.save(filename="field_tiff", directory_path=tmpdir, format="TIFF", value=field)
field_tiff = tifffile.imread(Path(tmpdir, "field_tiff.tiff"))
assert field_tiff.shape == field.data.shape
assert field_tiff.dtype == np.float32
assert np.allclose(field_tiff, field.data.astype(np.float32))
node.save(filename="field_png", directory_path=tmpdir, format="PNG", value=field)
field_png = np.asarray(PILImage.open(Path(tmpdir, "field_png.png")))
assert field_png.shape == (2, 2, 3)
assert field_png.dtype == np.uint8
node.save(filename="field_npz", directory_path=tmpdir, format="NPZ", value=field)
field_npz = np.load(Path(tmpdir, "field_npz.npz"))
assert np.allclose(field_npz["field"], field.data)
image = np.array([[[255, 0, 0], [0, 255, 0]], [[0, 0, 255], [255, 255, 0]]], dtype=np.uint8)
node.save(filename="image_png", directory_path=tmpdir, format="PNG", value=image)
image_png = np.asarray(PILImage.open(Path(tmpdir, "image_png.png")))
assert image_png.shape == image.shape
assert np.array_equal(image_png, image)
node.save(filename="image_tiff", directory_path=tmpdir, format="TIFF", value=image)
image_tiff = tifffile.imread(Path(tmpdir, "image_tiff.tiff"))
assert image_tiff.shape == image.shape
assert image_tiff.dtype == np.uint8
assert np.array_equal(image_tiff, image)
node.save(filename="image_npz", directory_path=tmpdir, format="NPZ", value=image)
image_npz = np.load(Path(tmpdir, "image_npz.npz"))
assert np.array_equal(image_npz["image"], image)
annotation_image = ImageData(image, metadata={"annotation_context": {"si_unit_xy": "um", "si_unit_z": "nm"}})
node.save(filename="annotation_png", directory_path=tmpdir, format="PNG", value=annotation_image)
assert np.array_equal(np.asarray(PILImage.open(Path(tmpdir, "annotation_png.png"))), image)
node.save(filename="annotation_tiff", directory_path=tmpdir, format="TIFF", value=annotation_image)
assert np.array_equal(tifffile.imread(Path(tmpdir, "annotation_tiff.tiff")), image)
node.save(filename="annotation_npz", directory_path=tmpdir, format="NPZ", value=annotation_image)
assert np.array_equal(np.load(Path(tmpdir, "annotation_npz.npz"))["image"], image)
measure_table = RecordTable([
{"quantity": "Rq", "value": 1.23, "unit": "nm"},
{"quantity": "Ra", "value": 0.98, "unit": "nm"},
])
node.save(filename="measurements_csv", directory_path=tmpdir, format="CSV", value=measure_table)
measure_csv = Path(tmpdir, "measurements_csv.csv").read_text(encoding="utf-8")
assert "quantity,value,unit" in measure_csv
assert "Rq,1.23,nm" in measure_csv
node.save(filename="measurements_json", directory_path=tmpdir, format="JSON", value=measure_table)
assert json.loads(Path(tmpdir, "measurements_json.json").read_text(encoding="utf-8")) == list(measure_table)
record_table = DataTable([
{"label": "particle-1", "height": 12.0, "area": 44.0},
{"label": "particle-2", "height": 8.0, "area": 21.0},
])
node.save(filename="records_csv", directory_path=tmpdir, format="CSV", value=record_table)
record_csv = Path(tmpdir, "records_csv.csv").read_text(encoding="utf-8")
assert "label,height,area" in record_csv
assert "particle-1,12.0,44.0" in record_csv
node.save(filename="records_json", directory_path=tmpdir, format="JSON", value=record_table)
assert json.loads(Path(tmpdir, "records_json.json").read_text(encoding="utf-8")) == list(record_table)
mesh = MeshModel(
vertices=np.array([[0, 0, 0], [1, 0, 0], [0, 1, 0]], dtype=np.float32),
faces=np.array([[0, 1, 2]], dtype=np.int32),
)
node.save(filename="triangle", directory_path=tmpdir, format="OBJ", value=mesh)
obj_text = Path(tmpdir, "triangle.obj").read_text(encoding="utf-8")
assert "v 0.0 0.0 0.0" in obj_text
assert "f 1 2 3" in obj_text
node.save(filename="triangle", directory_path=tmpdir, format="STL", value=mesh)
stl_text = Path(tmpdir, "triangle.stl").read_text(encoding="utf-8")
assert stl_text.startswith("solid argonode")
assert "facet normal" in stl_text
try:
node.save(filename="triangle", directory_path=tmpdir, format="PNG", value=mesh)
assert False, "Mesh should only be saveable as OBJ or STL"
except ValueError:
pass
try:
node.save(filename="field_bad", directory_path=tmpdir, format="CSV", value=field)
assert False, "DATA_FIELD should reject unsupported save formats"
except ValueError:
pass