low pri features
This commit is contained in:
143
backend/nodes/calibration.py
Normal file
143
backend/nodes/calibration.py
Normal file
@@ -0,0 +1,143 @@
|
||||
"""Calibration — apply lateral and height calibration corrections."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import numpy as np
|
||||
|
||||
from backend.node_registry import register_node
|
||||
from backend.data_types import DataField
|
||||
|
||||
|
||||
@register_node(display_name="Calibration")
|
||||
class Calibration:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"field": ("DATA_FIELD",),
|
||||
"xy_mode": (["keep", "set_size", "scale"], {"default": "keep"}),
|
||||
"z_mode": (["keep", "set_range", "scale", "offset"], {"default": "keep"}),
|
||||
"xreal_new": ("FLOAT", {
|
||||
"default": 1e-6,
|
||||
"min": 1e-12,
|
||||
"max": 1.0,
|
||||
"step": 1e-9,
|
||||
"show_when_widget_value": {"xy_mode": ["set_size"]},
|
||||
}),
|
||||
"yreal_new": ("FLOAT", {
|
||||
"default": 1e-6,
|
||||
"min": 1e-12,
|
||||
"max": 1.0,
|
||||
"step": 1e-9,
|
||||
"show_when_widget_value": {"xy_mode": ["set_size"]},
|
||||
}),
|
||||
"xy_scale": ("FLOAT", {
|
||||
"default": 1.0,
|
||||
"min": 0.001,
|
||||
"max": 1000.0,
|
||||
"step": 0.001,
|
||||
"show_when_widget_value": {"xy_mode": ["scale"]},
|
||||
}),
|
||||
"z_min": ("FLOAT", {
|
||||
"default": 0.0,
|
||||
"min": -1e-3,
|
||||
"max": 1e-3,
|
||||
"step": 1e-12,
|
||||
"show_when_widget_value": {"z_mode": ["set_range"]},
|
||||
}),
|
||||
"z_max": ("FLOAT", {
|
||||
"default": 1e-9,
|
||||
"min": -1e-3,
|
||||
"max": 1e-3,
|
||||
"step": 1e-12,
|
||||
"show_when_widget_value": {"z_mode": ["set_range"]},
|
||||
}),
|
||||
"z_scale": ("FLOAT", {
|
||||
"default": 1.0,
|
||||
"min": 0.001,
|
||||
"max": 1000.0,
|
||||
"step": 0.001,
|
||||
"show_when_widget_value": {"z_mode": ["scale"]},
|
||||
}),
|
||||
"z_offset": ("FLOAT", {
|
||||
"default": 0.0,
|
||||
"min": -1e-3,
|
||||
"max": 1e-3,
|
||||
"step": 1e-12,
|
||||
"show_when_widget_value": {"z_mode": ["offset"]},
|
||||
}),
|
||||
"xy_unit": ("STRING", {"default": ""}),
|
||||
"z_unit": ("STRING", {"default": ""}),
|
||||
}
|
||||
}
|
||||
|
||||
OUTPUTS = (
|
||||
('DATA_FIELD', 'result'),
|
||||
)
|
||||
FUNCTION = "process"
|
||||
|
||||
DESCRIPTION = (
|
||||
"Apply lateral and height calibration corrections to a DATA_FIELD. "
|
||||
"Lateral mode can set explicit physical size or scale uniformly. "
|
||||
"Height mode can rescale to a target range, multiply by a factor, "
|
||||
"or add a constant offset. Optionally override the XY or Z unit strings. "
|
||||
"Equivalent to Gwyddion's calibrate functionality."
|
||||
)
|
||||
|
||||
def process(
|
||||
self,
|
||||
field: DataField,
|
||||
xy_mode: str,
|
||||
z_mode: str,
|
||||
xreal_new: float,
|
||||
yreal_new: float,
|
||||
xy_scale: float,
|
||||
z_min: float,
|
||||
z_max: float,
|
||||
z_scale: float,
|
||||
z_offset: float,
|
||||
xy_unit: str,
|
||||
z_unit: str,
|
||||
) -> tuple:
|
||||
data = np.asarray(field.data, dtype=np.float64).copy()
|
||||
xreal = float(field.xreal)
|
||||
yreal = float(field.yreal)
|
||||
si_unit_xy = field.si_unit_xy
|
||||
si_unit_z = field.si_unit_z
|
||||
|
||||
# --- lateral calibration ---
|
||||
if xy_mode == "set_size":
|
||||
xreal = float(xreal_new)
|
||||
yreal = float(yreal_new)
|
||||
elif xy_mode == "scale":
|
||||
xreal *= float(xy_scale)
|
||||
yreal *= float(xy_scale)
|
||||
# "keep" → no change
|
||||
|
||||
# --- height calibration ---
|
||||
if z_mode == "set_range":
|
||||
cur_min = float(data.min())
|
||||
cur_max = float(data.max())
|
||||
if cur_max > cur_min:
|
||||
data = float(z_min) + (data - cur_min) * (float(z_max) - float(z_min)) / (cur_max - cur_min)
|
||||
else:
|
||||
data[:] = float(z_min)
|
||||
elif z_mode == "scale":
|
||||
data *= float(z_scale)
|
||||
elif z_mode == "offset":
|
||||
data += float(z_offset)
|
||||
# "keep" → no change
|
||||
|
||||
# --- unit overrides ---
|
||||
if xy_unit:
|
||||
si_unit_xy = xy_unit
|
||||
if z_unit:
|
||||
si_unit_z = z_unit
|
||||
|
||||
return (field.replace(
|
||||
data=data,
|
||||
xreal=xreal,
|
||||
yreal=yreal,
|
||||
si_unit_xy=si_unit_xy,
|
||||
si_unit_z=si_unit_z,
|
||||
),)
|
||||
Reference in New Issue
Block a user