fix value display node

This commit is contained in:
2026-03-29 12:13:08 -07:00
parent 80b74dfdfd
commit e3c381ee07
9 changed files with 207 additions and 31 deletions

View File

@@ -43,10 +43,9 @@ from backend.nodes import (
markup,
preview_image,
statistics,
value_io,
view_3d,
print_table,
value_display,
# Analysis
curvature,
fractal_dimension,
histogram,

View File

@@ -154,13 +154,12 @@ def _compute_curvature_results(
+ coeffs[5] * y_norm * y_norm
)
r1 = float("inf") if abs(kappa1) <= 1e-14 else float(1.0 / (q * q * kappa1))
r2 = float("inf") if abs(kappa2) <= 1e-14 else float(1.0 / (q * q * kappa2))
#todo: fix inf case
r1 = float(np.inf) if abs(kappa1) <= 1e-14 else float(1.0 / (q * q * kappa1))
r2 = float(np.inf) if abs(kappa2) <= 1e-14 else float(1.0 / (q * q * kappa2))
x0 = float(xc / q + 0.5 * xreal + field.xoff)
y0 = float(yc / q + 0.5 * yreal + field.yoff)
print(f"debug: {x0}, {y0}, {r1}, {r2}")
return {
"degree": float(degree),
"x0": x0,
@@ -292,8 +291,8 @@ class Curvature:
OUTPUTS = (
('ANNOTATION_SOURCE', 'output'),
('RECORD_TABLE', 'measurements'),
('LINE', 'profile_x'),
('LINE', 'profile_y'),
('LINE', 'profile_a'),
('LINE', 'profile_b'),
)
FUNCTION = "process"
@@ -340,7 +339,7 @@ class Curvature:
profiles = []
for pair in intersections[:2]:
profiles.append(_profile_from_intersections(field, pair[1], pair[0]))
profiles.append(_profile_from_intersections(field, pair[0], pair[1]))
while len(profiles) < 2:
profiles.append(_empty_profile(field.si_unit_xy, field.si_unit_z))
@@ -360,7 +359,7 @@ class Curvature:
preview_base = render_datafield_preview(field, field.colormap)
panels = []
for p, title in zip(profiles, ["X Principal Axis", "Y Principal Axis"]):
for p, title in zip(profiles, ["Principal Axis A", "Principal Axis B"]):
if len(p.data) > 0:
panels.append({
"title": title,
@@ -376,7 +375,7 @@ class Curvature:
})
emit_preview({"kind": "panels", "panels": panels})
# emit_table(table)
emit_table(table)
if warnings:
emit_warning(warnings[0])

View File

@@ -4,6 +4,7 @@ Shared helper functions for argonode nodes.
from __future__ import annotations
import json
import re
from functools import lru_cache
from pathlib import Path
from typing import Callable
@@ -16,6 +17,62 @@ from backend.runtime_paths import demo_dir, input_dir, output_dir
# Scalar payload helpers (from display.py)
# ---------------------------------------------------------------------------
_SI_PREFIXES: dict[str, float] = {
'Y': 1e24, 'Z': 1e21, 'E': 1e18, 'P': 1e15, 'T': 1e12,
'G': 1e9, 'M': 1e6, 'k': 1e3,
'm': 1e-3, 'u': 1e-6, 'µ': 1e-6, 'n': 1e-9, 'p': 1e-12,
'f': 1e-15, 'a': 1e-18, 'z': 1e-21, 'y': 1e-24,
}
_PREFIXABLE_UNITS: frozenset[str] = frozenset({
'm', 's', 'A', 'V', 'W', 'Hz', 'F', 'C', 'J', 'N', 'Pa',
'T', 'H', 'S', 'g', 'K', 'Ohm', 'ohm', 'Ω',
})
_NUMBER_RE = re.compile(
r'^([+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?)\s*(.*)?$'
)
def parse_number_with_unit(text: str) -> tuple[float, str]:
"""Parse a string like '1.5 nm' into (1.5e-9, 'm').
The numeric part may use scientific notation. The unit is stripped of any
recognised SI prefix and the raw value is scaled accordingly, so the
returned float is always in the base SI unit. Units that are not
prefixable are returned unchanged alongside the unscaled value.
Examples::
parse_number_with_unit("1 um") → (1e-6, "m")
parse_number_with_unit("500 nm") → (5e-7, "m")
parse_number_with_unit("3.14") → (3.14, "")
parse_number_with_unit("2 kHz") → (2000.0, "Hz")
"""
text = text.strip()
if not text:
return 0.0, ""
m = _NUMBER_RE.match(text)
if not m:
raise ValueError(f"Cannot parse number: {text!r}")
numeric = float(m.group(1))
unit_str = (m.group(2) or "").strip()
if not unit_str:
return numeric, ""
# Try prefix + base-unit split (handle multi-byte µ as a prefix)
if len(unit_str) >= 2:
prefix_char = unit_str[0]
rest = unit_str[1:]
if prefix_char in _SI_PREFIXES and rest in _PREFIXABLE_UNITS:
return numeric * _SI_PREFIXES[prefix_char], rest
return numeric, unit_str
def _scalar_payload(value: float, unit: str = "") -> dict:
payload = {"value": float(value)}
if isinstance(unit, str) and unit.strip():
@@ -24,7 +81,7 @@ def _scalar_payload(value: float, unit: str = "") -> dict:
# ---------------------------------------------------------------------------
# Measurement helpers (from display.py — used by ValueDisplay)
# Measurement helpers (from display.py — used by ValueIO)
# ---------------------------------------------------------------------------
def _measurement_names(table: list) -> list[str]:

View File

@@ -2,18 +2,21 @@ from __future__ import annotations
from backend.node_registry import register_node
from backend.execution_context import emit_table, emit_value
from backend.data_types import RecordTable
from backend.nodes.helpers import _measurement_entry, _measurement_value, _scalar_payload
from backend.nodes.helpers import _measurement_entry, _measurement_value, _scalar_payload, parse_number_with_unit
@register_node(display_name="Value Display")
class ValueDisplay:
class ValueIO:
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"value": ("FLOAT", {
"accepted_types": ["RECORD_TABLE"],
"socket_only": True,
"number_input": ("STRING", {
"text_input": True,
"default": "0",
"placeholder": "e.g. 1.5 nm",
"hide_when_input_connected": "value",
"hide_label": True,
}),
"measurement": ("STRING", {
"default": "",
@@ -22,7 +25,13 @@ class ValueDisplay:
"value": ["RECORD_TABLE"],
},
}),
}
},
"optional": {
"value": ("FLOAT", {
"accepted_types": ["RECORD_TABLE"],
"socket_only": True,
}),
},
}
OUTPUTS = (
@@ -35,14 +44,16 @@ class ValueDisplay:
_broadcast_value_fn = None
_current_node_id: str = ""
def display_value(self, value, measurement: str = "") -> tuple:
def display_value(self, number_input: str = "0", value=None, measurement: str = "") -> tuple:
unit = ""
if isinstance(value, RecordTable):
emit_table(value)
row = _measurement_entry(value, measurement)
numeric = _measurement_value(value, measurement)
unit = row.get("unit", "") if isinstance(row.get("unit"), str) else ""
else:
elif value is not None:
numeric = float(value)
else:
numeric, unit = parse_number_with_unit(str(number_input))
emit_value(_scalar_payload(numeric, unit))
return (numeric,)