clean up node naming

This commit is contained in:
2026-03-28 21:06:22 -07:00
parent 60cc3af9c2
commit b8133c064a
33 changed files with 412 additions and 67 deletions

View File

@@ -585,13 +585,16 @@ class ExecutionEngine:
plt.close(fig)
fallback_image = f"data:image/png;base64,{base64.b64encode(buf.getvalue()).decode()}"
return {
result_dict = {
"kind": "line_plot",
"line": y.tolist(),
"x_axis": x.tolist(),
"interactive": False,
"fallback_image": fallback_image,
}
if y_meta is not None and y_meta.x_unit:
result_dict["x_unit"] = y_meta.x_unit
return result_dict
except Exception:
return None

View File

@@ -1,63 +1,60 @@
# Import all node modules to trigger @register_node decorators.
from backend.nodes import (
# IO
colormap,
crop_resize,
fft_2d_invert,
filter_fft_1d,
filter_fft_2d,
filter_gaussian,
filter_median,
flip,
font,
image,
ibw_note,
image_demo,
folder,
coordinate,
coordinate_pair,
level_facet,
level_plane,
level_poly,
mask_draw,
mask_threshold,
note,
number,
range_slider,
rotate,
save,
save_image,
# Filters
gaussian_filter,
median_filter,
edge_detect,
fft_filter_1d,
fft_filter_2d,
# Modify
colormap_adjust,
crop_resize_field,
rotate_field,
flip_field,
# Level
plane_level_field,
facet_level_field,
poly_level_field,
fix_zero,
line_correction,
# Mask
draw_mask,
threshold_mask,
mask_morphology,
mask_invert,
mask_operations,
grain_distance_transform,
save_layers,
# Correction
scar_removal,
# Display
color_map,
font_node,
annotations,
angle_measure,
markup,
preview_image,
statistics,
view_3d,
print_table,
value_display,
# Analysis
curvature,
fractal_dimension,
statistics_node,
histogram,
acf_2d,
acf_1d,
cursors,
fft_2d,
psdf,
inverse_fft_2d,
cross_section,
stats,
watershed_segmentation,

View File

@@ -98,6 +98,7 @@ class Cursors:
"section_title": "Cursors",
"line": y.tolist(),
"x_axis": x.tolist(),
"x_unit": x_unit,
"x1": x1,
"x2": x2,
"y1": float(y1),

View File

@@ -21,7 +21,7 @@ class FFT1D:
OUTPUTS = (
("LINE", "frequency_plot"),
('RECORD_TABLE', 'measurement'),
('RECORD_TABLE', 'max'),
)
FUNCTION = "process"

View File

@@ -9,7 +9,7 @@ from backend.nodes.spectral_common import (
)
@register_node(display_name="2D FFT")
@register_node(display_name="FFT 2D")
class FFT2D:
@classmethod
def INPUT_TYPES(cls):

View File

@@ -5,7 +5,7 @@ from backend.data_types import LineData
from backend.nodes.helpers import _cached_1d_transfer
@register_node(display_name="1D FFT Filter")
@register_node(display_name="FFT Filter 1D")
class FFTFilter1D:
"""Bandpass / lowpass / highpass / notch filtering of 1-D line profiles.

View File

@@ -5,7 +5,7 @@ from backend.data_types import DataField
from backend.nodes.helpers import _cached_2d_transfer
@register_node(display_name="2D FFT Filter")
@register_node(display_name="FFT Filter 2D")
class FFTFilter2D:
"""Frequency-domain filtering of 2-D data fields (images).

View File

@@ -80,6 +80,7 @@ class Histogram:
"section_title": "Histogram",
"line": counts.tolist(),
"x_axis": bin_centers.astype(np.float64).tolist(),
"x_unit": field.si_unit_z,
"x1": float(np.clip(x1, 0.0, 1.0)),
"x2": float(np.clip(x2, 0.0, 1.0)),
"y1": float(y1),

View File

@@ -1,8 +1,8 @@
from __future__ import annotations
import numpy as np
from backend.node_registry import register_node
from backend.execution_context import emit_preview
from backend.data_types import DataField, encode_preview
from backend.execution_context import emit_preview, emit_overlay
from backend.data_types import DataField, encode_preview, RecordTable
from backend.nodes.helpers import _mask_overlay
@@ -15,14 +15,15 @@ class ThresholdMask:
return {
"required": {
"field": ("DATA_FIELD",),
"method": (["otsu", "absolute", "relative"],),
"threshold": ("FLOAT", {"default": 0.0, "min": -1e9, "max": 1e9, "step": 0.001}),
"method": (["absolute", "relative", "otsu"],),
"threshold": ("FLOAT", {"default": 0.0, "min": -1e9, "max": 1e9, "step": 0.001, "socket_only": True}),
"direction": (["above", "below"],),
}
}
OUTPUTS = (
('IMAGE', 'mask'),
('RECORD_TABLE', 'threshold'),
)
FUNCTION = "process"
@@ -38,6 +39,12 @@ class ThresholdMask:
def process(self, field: DataField, method: str, threshold: float, direction: str) -> tuple:
data = field.data
raw_counts, bin_edges = np.histogram(data.ravel(), bins=256)
bin_centers = 0.5 * (bin_edges[:-1] + bin_edges[1:])
counts = raw_counts.astype(np.float64)
xmin = float(bin_centers[0]) if len(bin_centers) else 0.0
xmax = float(bin_centers[-1]) if len(bin_centers) else 1.0
if method == "otsu":
from skimage.filters import threshold_otsu
t = threshold_otsu(data)
@@ -49,12 +56,31 @@ class ThresholdMask:
else:
raise ValueError(f"Unknown threshold method: {method}")
span = xmax - xmin if xmax != xmin else 1.0
threshold_frac = float(np.clip((t - xmin) / span, 0.0, 1.0))
emit_overlay({
"kind": "threshold_histogram",
"section_title": "Histogram",
"line": counts.tolist(),
"x_axis": bin_centers.tolist(),
"x_unit": field.si_unit_z,
"threshold_frac": threshold_frac,
"x_min": xmin,
"x_max": xmax,
"method": method,
"locked": method == "otsu",
})
if direction == "above":
mask = (data >= t).astype(np.uint8) * 255
else:
mask = (data < t).astype(np.uint8) * 255
overlay = _mask_overlay(field, mask)
emit_preview(encode_preview(overlay))
emit_preview(encode_preview(_mask_overlay(field, mask)))
return (mask,)
table = RecordTable([
{"quantity": "threshold", "value": threshold, "unit": field.si_unit_xy},
])
return (mask, table)