clean up node naming
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -21,7 +21,7 @@ class FFT1D:
|
||||
|
||||
OUTPUTS = (
|
||||
("LINE", "frequency_plot"),
|
||||
('RECORD_TABLE', 'measurement'),
|
||||
('RECORD_TABLE', 'max'),
|
||||
)
|
||||
|
||||
FUNCTION = "process"
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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)
|
||||
Reference in New Issue
Block a user