add help docs and ?

This commit is contained in:
2026-03-30 23:10:42 -07:00
parent ced43bec4f
commit 63d76bac72
76 changed files with 2184 additions and 1 deletions

View File

@@ -271,6 +271,18 @@ def create_app(
content_type="application/json",
)
async def get_node_doc(request: web.Request) -> web.Response:
name = request.rel_url.query.get("name", "").strip()
if not name:
raise web.HTTPBadRequest(reason="Missing 'name' query parameter")
docs_dir = project_root() / "docs" / "nodes"
# Try exact match first, then fall back to replacing " / " with "-"
candidates = [docs_dir / f"{name}.md", docs_dir / f"{name.replace(' / ', '-')}.md"]
for path in candidates:
if path.exists() and path.is_file():
return web.Response(text=path.read_text(encoding="utf-8"), content_type="text/plain")
raise web.HTTPNotFound(reason=f"No documentation found for '{name}'")
async def list_files(request: web.Request) -> web.Response:
session_id = require_session_id(request)
input_path = session_input_dir(session_id)
@@ -532,6 +544,7 @@ def create_app(
app.router.add_post("/download", download_file)
app.router.add_post("/save-workflow-png", save_workflow_png)
app.router.add_get("/channels", get_channels)
app.router.add_get("/docs", get_node_doc)
app.router.add_post("/prompt", submit_prompt)
app.router.add_get("/ws", websocket_handler)

33
docs/nodes/3D View.md Normal file
View File

@@ -0,0 +1,33 @@
# 3D View
Interactive 3D surface view of a DATA_FIELD. Use the mesh input for geometry and optionally a second map input for coloring. Drag to rotate, middle-drag to pan, and right-drag or scroll to zoom.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Height field used for mesh geometry |
| map_field | DATA_FIELD | No | Optional separate field used for surface coloring |
| colormap_map | COLORMAP | No | Colormap socket; overrides the colormap widget |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| mesh | MESH_MODEL | Triangulated 3D surface mesh |
| viewport | IMAGE | Snapshot of the 3D viewport |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| colormap | dropdown | auto | Colormap preset applied to the surface; hidden when colormap_map is connected |
| z_scale | FLOAT | 1.0 | Height exaggeration factor (range 0.110.0) |
| resolution | INT | 128 | Downsampling resolution for mesh generation (32512) |
| make_solid | BOOLEAN | False | When enabled adds a flat base and side walls to close the mesh |
## Limitations
- Resolution is applied by uniform subsampling; fine features smaller than one mesh step may be lost.
- Non-square pixels emit a warning and the 3D surface represents physical scan area, not pixel grid.
- Very high resolution values (close to 512) with large fields may be slow to render.

27
docs/nodes/ACF 1D.md Normal file
View File

@@ -0,0 +1,27 @@
# ACF 1D
Compute the one-dimensional autocorrelation function of a line profile. Only positive lags are output on the x-axis. The measurement table reports the dominant period from the first positive peak.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| profile | LINE | Yes | Input line profile |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| acf | LINE | Autocorrelation function (positive lags only) |
| measurement | RECORD_TABLE | Table with the dominant peak period |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| level | dropdown | mean | Pre-processing: subtract mean before correlation, or none |
## Limitations
- Only one-sided (positive lag) ACF is returned.
- Peak period detection finds only the first local maximum; multi-periodic signals report only the shortest detected period.

26
docs/nodes/ACF 2D.md Normal file
View File

@@ -0,0 +1,26 @@
# ACF 2D
Compute the two-dimensional autocorrelation function with Gwyddion-style mean or plane levelling before correlation. The output is centered on zero shift and uses default half-range extents.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Input height field |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| acf | DATA_FIELD | 2D autocorrelation field centered on zero shift |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| level | dropdown | mean | Pre-processing applied before correlation: mean subtraction, plane subtraction, or none |
## Limitations
- Output is not normalized to [1, 1]; peak value equals the field variance.
- Plane levelling assumes a linear trend; strongly curved surfaces may not detrend correctly.

View File

@@ -0,0 +1,28 @@
# Angle Measure
Measure the included angle between two draggable line segments over a DATA_FIELD or IMAGE. Drag either endpoint to change that arm, drag the middle joint to move the whole widget, and drag the angle label to reposition it.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| input | ANNOTATION_SOURCE (DATA_FIELD or IMAGE) | Yes | Background image or field to annotate |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| output | ANNOTATION_SOURCE | Input with the angle overlay attached |
| measurements | RECORD_TABLE | Angle in degrees, arm lengths, and arm/vertex coordinates |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| color | STRING (color picker) | #ff9800 | Overlay color for the angle arms and arc |
| stroke_width | FLOAT | 1.35 | Line thickness in display pixels (0.356.0) |
## Limitations
- Coordinates are stored as fractions of the image dimensions; physical units depend on the input field's calibration.
- Angle measurement is the included angle at the vertex, always in [0°, 180°].

30
docs/nodes/Annotations.md Normal file
View File

@@ -0,0 +1,30 @@
# Annotations
Attach optional publication-style annotations (scale bar, color-map legend) to a DATA_FIELD without flattening the raw data, or annotate an IMAGE that carries viewport metadata from View3D.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| input | ANNOTATION_SOURCE (DATA_FIELD or IMAGE) | Yes | Field or image to annotate |
| colormap_map | COLORMAP | No | Colormap socket; overrides the colormap widget |
| font | FONT | No | Font specification for annotation text |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| output | ANNOTATION_SOURCE | Input with annotation overlay attached |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| colormap | dropdown | auto | Colormap for the legend; hidden when colormap_map is connected |
| show_scale_bar | BOOLEAN | True | Render a physical scale bar |
| show_color_map | BOOLEAN | True | Render a color-map legend with min/mid/max values |
| text_size | FLOAT | 14.0 | Font size in points for annotation labels (696) |
## Limitations
- Scale bar and color-map legend require the input to carry physical dimension and unit metadata; plain images without metadata will emit a warning and the feature will be skipped.

View File

@@ -0,0 +1,32 @@
# Blind Tip Estimate
Blind tip estimation from a measured SPM image using the Villarrubia algorithm. Iteratively refines the tip shape using only the sharpest image features without knowing the true surface in advance.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Measured SPM surface image |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| tip | DATA_FIELD | Estimated tip shape (apex = maximum value, edges = 0) |
| certainty | IMAGE | Map marking surface pixels where the tip was in unambiguous single contact |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| n_pixels | INT | 33 | Tip grid size in pixels (odd values only, 3129) |
| threshold | FLOAT | 0.0 | Noise floor in metres; increase if the estimated tip is unrealistically sharp |
| method | dropdown | partial | partial: uses local maxima only (faster, needs sharp isolated features); full: uses all points above morphological opening (slower, more robust) |
| use_edges | BOOLEAN | False | When enabled, also uses image edge pixels as refinement candidates |
## Limitations
- Requires sharp, isolated features on the surface for reliable results.
- Output tip has the same pixel size as the input field; tip deconvolution requires matching pixel sizes.
- Large tip sizes (n_pixels > ~65) or the full method on large images can be slow.
- Equivalent to gwy_tip_estimate_partial / gwy_tip_estimate_full + gwy_tip_cmap.

26
docs/nodes/Color Map.md Normal file
View File

@@ -0,0 +1,26 @@
# Color Map
Build a reusable colormap. Choose a preset from the built-in palette list, or create a custom gradient with min/max colours and any number of intermediate stops.
## Inputs
None.
## Outputs
| Name | Type | Description |
|------|------|-------------|
| colormap | COLORMAP | Colormap specification for use with other nodes |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| mode | dropdown | preset | Switch between preset and custom gradient modes |
| preset | dropdown | viridis | Built-in colormap preset name; visible when mode is preset |
| stops | STRING (colormap editor) | default gradient | JSON array of color stops for the custom gradient; visible when mode is custom |
## Limitations
- Custom colormaps must include at least a minimum and maximum color stop.
- Stops must be valid JSON; invalid JSON will raise an error.

View File

@@ -0,0 +1,28 @@
# Colormap Adjust
Adjust how a DATA_FIELD maps into its colormap without changing the underlying data. offset and scale operate in normalized display coordinates; Auto resets to the full data range.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Input field whose colormap mapping is adjusted |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| field | DATA_FIELD | Field with updated display_offset and display_scale metadata |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| offset | FLOAT | 0.0 | Shift the colormap center in normalized units (1 to 1) |
| scale | FLOAT | 1.0 | Zoom the colormap range (0.054.0); values below 1 stretch contrast |
| auto | BUTTON | — | Reset offset to 0 and scale to 1 (full data range) |
## Limitations
- Only the display mapping metadata is changed; raw data values are unaffected.
- Scale must be positive and finite; zero or negative values raise an error.

View File

@@ -0,0 +1,24 @@
# Coordinate Pair
Combine two COORD values into a single COORDPAIR for use with nodes that accept a line segment or marker pair input.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| a | COORD | Yes | First coordinate (x, y) in fractional [0, 1] units |
| b | COORD | Yes | Second coordinate (x, y) in fractional [0, 1] units |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| coord_pair | COORDPAIR | Pair of coordinates as a single value |
## Controls
None.
## Limitations
- Coordinates are expected to be in the [0, 1] fractional range; values outside this range may produce unexpected results in downstream nodes.

24
docs/nodes/Coordinate.md Normal file
View File

@@ -0,0 +1,24 @@
# Coordinate
Output a fractional (x, y) coordinate pair in [0, 1] for use with Cross Section, Cursors, or other nodes that accept a COORD input.
## Inputs
None.
## Outputs
| Name | Type | Description |
|------|------|-------------|
| point | COORD | Fractional (x, y) coordinate |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| x | FLOAT | 0.5 | Horizontal position as a fraction of image width (0 = left, 1 = right) |
| y | FLOAT | 0.5 | Vertical position as a fraction of image height (0 = top, 1 = bottom) |
## Limitations
- Values are clamped to [0, 1] by downstream nodes; this node does not enforce clamping itself.

31
docs/nodes/Crop-Resize.md Normal file
View File

@@ -0,0 +1,31 @@
# Crop / Resize
Crop a DATA_FIELD with a draggable rectangle defined by two corners, then optionally resize it. Cropping updates physical extents and offsets; resizing preserves the cropped physical size.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Input field to crop |
| corner_a | COORD | No | Locks the top-left corner of the crop box |
| corner_b | COORD | No | Locks the bottom-right corner of the crop box |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| field | DATA_FIELD | Cropped (and optionally resampled) field |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| target_width | INT | 0 | Output pixel width after resampling (0 = keep cropped width) |
| target_height | INT | 0 | Output pixel height after resampling (0 = keep cropped height) |
| interpolation | dropdown | bilinear | Resampling interpolation: bilinear, nearest, or bicubic |
## Limitations
- The crop region must have non-zero width and height; an error is raised otherwise.
- If only one of target_width or target_height is set, the other dimension is computed to preserve aspect ratio.
- Physical extents are scaled proportionally when resampling.

View File

@@ -0,0 +1,29 @@
# Cross Section
Extract a cross-section height profile along a line between two draggable points on a DATA_FIELD. Equivalent to gwy_data_field_get_profile.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Input height field |
| marker_pair | COORDPAIR | No | Locks both line endpoints from an external coordinate pair |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| profile | LINE | Height profile along the cross-section line |
| marker_pair | COORDPAIR | Current endpoint coordinates (passthrough for chaining) |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| extend | dropdown | none | none: profile between the two markers; to_edges: extend line to image borders |
| n_samples | INT | 0 | Number of sample points along the profile (0 = auto, one per pixel diagonal) |
## Limitations
- Profile is sampled using cubic spline interpolation (order 3); sharp step edges may show ringing.
- Physical x-axis of the output profile is the Euclidean distance in field xy units.

View File

@@ -0,0 +1,28 @@
# Cross-Correlate
Compute 2D cross-correlation between two fields. The correlation peak indicates the offset where the two fields best match. Useful for drift measurement and feature alignment. Equivalent to Gwyddion crosscor.c.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field_a | DATA_FIELD | Yes | First input field |
| field_b | DATA_FIELD | Yes | Second input field |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| correlation | DATA_FIELD | Cross-correlation map |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| mode | dropdown | same | Output size: full (Na+Nb1), same (same as field_a), or valid (overlapping region only) |
| normalize | BOOLEAN | True | Normalize the result to [1, 1] by dividing by the product of RMS values |
## Limitations
- Both fields must be of compatible numpy array types; very different sizes in full mode produce large outputs.
- Mean is subtracted before correlation; absolute offset information is lost.

26
docs/nodes/Cursors.md Normal file
View File

@@ -0,0 +1,26 @@
# Cursors
Place two draggable cursors on a line plot or 2D field to measure positions and deltas. On lines it reports x/y positions and dx/dy; on fields it reports x/y/z at both markers plus dx/dy/dz.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| line | LINE or DATA_FIELD | Yes | Input line profile or 2D field |
| coord_pair | COORDPAIR | No | Locks both cursor positions from an external coordinate pair |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| measurement | RECORD_TABLE | Positions, deltas, and lengths at the two cursor locations |
| coord_pair | COORDPAIR | Current cursor positions (passthrough for chaining) |
## Controls
None (cursor positions are set by dragging in the preview panel).
## Limitations
- When a COORDPAIR is connected, the cursor positions are locked and cannot be dragged interactively.
- On 2D fields, z values are sampled with bilinear (order 1) interpolation.

31
docs/nodes/Curvature.md Normal file
View File

@@ -0,0 +1,31 @@
# Curvature
Fit a quadratic surface and report the overall principal curvature radii and directions, matching Gwyddion's curvature feature. The output annotation marks the principal cross-sections and the node also returns the two corresponding height profiles.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Input topographic field |
| mask | IMAGE | No | Binary mask for including or excluding regions from the quadratic fit |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| output | ANNOTATION_SOURCE | Field with principal-axis lines overlaid |
| measurements | RECORD_TABLE | Curvature radii, principal-axis directions, center position and value |
| profile_a | LINE | Height profile along principal axis 1 |
| profile_b | LINE | Height profile along principal axis 2 |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| masking | dropdown | ignore | How to use the mask: ignore (fit all pixels), include (fit only masked pixels), or exclude (fit unmasked pixels) |
## Limitations
- Requires at least six usable pixels for the quadratic fit; fewer pixels produce no output.
- The fit assumes a globally smooth quadratic surface; locally rough or step-like surfaces give unreliable results.
- Requires compatible XY and Z physical units (e.g. both in metres).

View File

@@ -0,0 +1,30 @@
# Custom Convolution
Apply a user-defined convolution kernel to a DATA_FIELD. Enter rows of space-separated numbers. Equivalent to Gwyddion convolution_filter.c.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Input field to filter |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| result | DATA_FIELD | Filtered field |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| kernel | STRING (multiline) | "0 -1 0\n-1 5 -1\n0 -1 0" | Kernel rows, each as space-separated numbers on a new line |
| normalize | BOOLEAN | True | Divide the result by the sum of absolute kernel values to preserve amplitude |
| boundary | dropdown | reflect | Boundary handling: reflect, nearest, or wrap |
## Limitations
- Kernel must be a rectangle: all rows must have the same number of values.
- Maximum kernel size is 51×51; larger kernels are rejected.
- Non-finite values in the kernel are rejected and the input is returned unchanged.
- For large kernels, direct convolution can be slow; consider FFT Filter instead.

28
docs/nodes/Draw Mask.md Normal file
View File

@@ -0,0 +1,28 @@
# Draw Mask
Paint a binary mask directly over an image preview. Pen size controls newly drawn strokes, the Clear Mask button removes all strokes, and invert flips the final binary output.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Background field whose dimensions define the mask size |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| mask | IMAGE | Binary mask image (painted regions = white, background = black, or inverted) |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| pen_size | INT | 12 | Brush diameter in pixels for newly drawn strokes (1128) |
| invert | BOOLEAN | False | When enabled, swaps painted and unpainted regions |
| clear_mask | BUTTON | — | Clears all painted strokes |
## Limitations
- Strokes are stored as path data; very long painting sessions with many strokes may accumulate large state.
- The mask resolution matches the input field resolution and cannot be changed independently.

27
docs/nodes/Edge Detect.md Normal file
View File

@@ -0,0 +1,27 @@
# Edge Detect
Detect edges using Sobel, Prewitt, Laplacian, or Laplacian-of-Gaussian (LoG) operators. Equivalent to gwy_data_field_filter_sobel / gwy_data_field_filter_laplacian.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Input field |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| edges | DATA_FIELD | Edge-detected output field |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| method | dropdown | sobel | Edge detection operator: sobel, prewitt, laplacian, or log (Laplacian of Gaussian) |
| sigma | FLOAT | 1.0 | Gaussian smoothing sigma used only for the LoG operator (0.110.0) |
## Limitations
- sigma is ignored for sobel, prewitt, and laplacian methods.
- Sobel and Prewitt return gradient magnitude; Laplacian and LoG return signed second-derivative values.

28
docs/nodes/Entropy.md Normal file
View File

@@ -0,0 +1,28 @@
# Entropy
Compute the Shannon entropy of the height or slope distribution. H = −Σ p·ln(p). Equivalent to Gwyddion entropy.c.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Input field |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| entropy | FLOAT | Shannon entropy in nats |
| normalised_entropy | FLOAT | Entropy divided by ln(n_bins), in [0, 1] |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| mode | dropdown | height values | Compute entropy of height values or slope magnitude |
| n_bins | INT | 256 | Number of histogram bins for probability estimation (161024) |
## Limitations
- Entropy is sensitive to n_bins; very few bins underestimate entropy while very many bins overestimate it for small fields.
- Non-finite pixel values are removed before binning.

26
docs/nodes/FFT 1D.md Normal file
View File

@@ -0,0 +1,26 @@
# FFT 1D
Compute the FFT amplitude spectrum of a line profile and identify the dominant period. The output x-axis is period (not frequency), sorted from short to long.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| profile | LINE | Yes | Input line profile |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| frequency_plot | LINE | FFT amplitude spectrum vs. period |
| max | RECORD_TABLE | Table with the peak period |
## Controls
None.
## Limitations
- The DC component is excluded from the output.
- Spectrum is one-sided (real FFT); the x-axis shows period, not frequency.
- No windowing is applied; spectral leakage may affect results on non-periodic inputs.

30
docs/nodes/FFT 2D.md Normal file
View File

@@ -0,0 +1,30 @@
# FFT 2D
Compute the 2D FFT with optional windowing and mean/plane subtraction. Outputs log magnitude, magnitude, phase, and PSDF as separate channels. Equivalent to gwy_data_field_2dfft / gwy_data_field_2dpsdf.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Input spatial-domain field |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| log_magnitude | DATA_FIELD | log(1 + |F|) of the 2D FFT, centered on DC |
| magnitude | DATA_FIELD | |F| of the 2D FFT, centered on DC |
| phase | DATA_FIELD | Phase angle of the 2D FFT in radians, centered on DC |
| psdf | DATA_FIELD | 2D power spectral density function |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| windowing | dropdown | hann | Window function applied before FFT: hann, hamming, blackman, or none |
| level | dropdown | mean | Pre-processing: subtract mean, subtract plane, or none |
## Limitations
- Output fields are in the frequency domain; physical units on axes are spatial frequency (1/m).
- Phase output uses the raw FFT phase and is sensitive to field origin; it is most useful when paired with the Inverse 2D FFT node.

29
docs/nodes/FFT Filter.md Normal file
View File

@@ -0,0 +1,29 @@
# FFT Filter
Frequency-domain filtering of a line profile or 2D data field using a Butterworth transfer function. Connect a LINE for 1D filtering or a DATA_FIELD for 2D filtering; the output mirrors the input type. Equivalent to Gwyddion fft_filter_1d / fft_filter_2d.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| input | LINE or DATA_FIELD | Yes | Input line or field to filter |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| filtered | LINE or DATA_FIELD | Filtered output matching the input type |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| filter_type | dropdown | lowpass | Filter mode: lowpass, highpass, bandpass, or notch (band-reject) |
| cutoff | FLOAT | 0.1 | Lower cutoff frequency as a fraction of Nyquist (0.0011.0) |
| cutoff_high | FLOAT | 0.4 | Upper cutoff for bandpass/notch modes (0.0011.0) |
| order | INT | 2 | Butterworth filter order; higher values give steeper roll-off (110) |
## Limitations
- cutoff_high is only used for bandpass and notch modes.
- The filter is applied in the frequency domain via FFT; very short lines may show wrap-around artefacts.

28
docs/nodes/Facet Level.md Normal file
View File

@@ -0,0 +1,28 @@
# Facet Level
Level a field by iteratively finding the dominant local facet orientation and subtracting the corresponding plane. Matches Gwyddion's facet-level behaviour. Supports mask include/exclude selection.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Input topographic field |
| mask | IMAGE | No | Binary mask for including or excluding facets from plane fitting |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| leveled | DATA_FIELD | Field with dominant facet plane subtracted |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| masking | dropdown | exclude | How to use the mask: exclude (ignore masked facets), include (use only masked facets), or ignore (use all facets) |
## Limitations
- Requires compatible XY and Z physical units for correct facet gradient estimation.
- Needs at least four valid facet cells; fields smaller than 2×2 pixels are not processed.
- Flat surfaces with no variation in facet orientation may not converge to a meaningful plane.

View File

@@ -0,0 +1,27 @@
# Field Arithmetic
Apply a point-wise arithmetic operation to two DATA_FIELDs of the same resolution. Equivalent to gwy_data_field_sum_fields / subtract_fields / multiply_fields / divide_fields / min_of_fields / max_of_fields / hypot_of_fields.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field_a | DATA_FIELD | Yes | First operand |
| field_b | DATA_FIELD | Yes | Second operand |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| result | DATA_FIELD | Result of the arithmetic operation (inherits metadata from field_a) |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| operation | dropdown | add | Element-wise operation: add, subtract, multiply, divide, min, max, or hypot (√(a²+b²)) |
## Limitations
- Both fields must have exactly the same pixel dimensions; mismatched sizes raise an error.
- divide may produce NaN or Inf pixels where field_b is zero.

25
docs/nodes/Fix Zero.md Normal file
View File

@@ -0,0 +1,25 @@
# Fix Zero
Shift data so that the minimum, mean, or median value becomes zero. Equivalent to fix_zero in Gwyddion's level.c.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Input field |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| zeroed | DATA_FIELD | Field shifted so the chosen reference is at zero |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| method | dropdown | min | Reference value to set to zero: min (lowest pixel), mean (average), or median |
## Limitations
- None.

25
docs/nodes/Flip.md Normal file
View File

@@ -0,0 +1,25 @@
# Flip
Reflect a DATA_FIELD across the X axis (top/bottom) or Y axis (left/right). Physical extents are preserved, and stored markup overlays are mirrored with the data.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Input field to flip |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| field | DATA_FIELD | Flipped field |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| axis | dropdown | x | Flip axis: x flips top/bottom (vertical mirror), y flips left/right (horizontal mirror) |
## Limitations
- None.

View File

@@ -0,0 +1,25 @@
# Float Slider
Interactive float slider node. Set min and max bounds, then drag the slider to output a FLOAT value.
## Inputs
None.
## Outputs
| Name | Type | Description |
|------|------|-------------|
| value | FLOAT | Current slider value |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| min_value | FLOAT | 0.0 | Lower bound of the slider range |
| max_value | FLOAT | 1.0 | Upper bound of the slider range |
| value | FLOAT (slider) | 0.5 | Current value within [min_value, max_value] |
## Limitations
- None.

24
docs/nodes/Folder.md Normal file
View File

@@ -0,0 +1,24 @@
# Folder
Pick a folder and output its directory path plus one file socket per compatible file inside it. Supported files include common images, .npy/.npz arrays, and .gwy/.sxm/.ibw scans.
## Inputs
None.
## Outputs
| Name | Type | Description |
|------|------|-------------|
| directory | DIRECTORY | The selected folder path |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| folder | FOLDER_PICKER | "" | Path to the folder to list |
## Limitations
- Only files with supported extensions are listed; subdirectories and unsupported file types are ignored.
- The number of file output sockets is determined at load time by the folder contents.

25
docs/nodes/Font.md Normal file
View File

@@ -0,0 +1,25 @@
# Font
Build a reusable font specification for annotation overlays. Choose a discovered system font, use the default fallback stack, or point to a custom font file.
## Inputs
None.
## Outputs
| Name | Type | Description |
|------|------|-------------|
| font | FONT | Font specification for use with Annotations and similar nodes |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| family | dropdown | System default | Font family name; includes discovered system fonts plus "Custom file" option |
| font_file | FILE_PICKER | "" | Path to a custom font file; visible only when family is set to "Custom file" |
## Limitations
- Custom font files must be in a format supported by the underlying font rendering library (e.g. TTF, OTF).
- System fonts are enumerated at startup; newly installed fonts require restarting the application.

View File

@@ -0,0 +1,27 @@
# Fractal Dimension
Calculate the surface fractal dimension using Gwyddion's partitioning, cube counting, triangulation, power-spectrum, or HHCF methods. The in-node graph shows the log-log curve and allows dragging the fit range.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Input surface field |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| dimension | FLOAT | Estimated fractal dimension |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| method | dropdown | partitioning | Algorithm: partitioning, cube_counting, triangulation, psdf (power spectrum), or hhcf (structure function) |
| interpolation | dropdown | linear | Interpolation used when resampling the field to a square grid: linear, nearest, or cubic |
## Limitations
- The field is resampled to a square grid internally; highly anisotropic scan sizes may introduce interpolation artefacts.
- Fit range can be adjusted interactively on the log-log plot; the default range covers the full data.

View File

@@ -0,0 +1,26 @@
# Gaussian Filter
Apply a Gaussian blur to a DATA_FIELD. Equivalent to gwy_data_field_filter_gaussian.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Input field to filter |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| filtered | DATA_FIELD | Gaussian-blurred field |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| sigma | FLOAT | 1.0 | Standard deviation of the Gaussian kernel in pixels (0.0150.0) |
## Limitations
- sigma is specified in pixels, not physical units; the effective physical blur depends on pixel size.
- Large sigma values (> ~20 pixels) are slow due to the large kernel.

26
docs/nodes/Gradient.md Normal file
View File

@@ -0,0 +1,26 @@
# Gradient
Compute the spatial gradient using a Sobel operator. Outputs the gradient magnitude, x-component, y-component, or azimuthal direction.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Input field |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| gradient | DATA_FIELD | Gradient output in the selected component |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| component | dropdown | magnitude | Output component: magnitude (√(gx²+gy²)), x (horizontal gradient), y (vertical gradient), or azimuth (angle in degrees) |
## Limitations
- Gradient components are in units of z_unit/xy_unit; azimuth is in degrees.
- Sobel operator uses a 3×3 kernel; sub-pixel features smaller than one pixel cannot be resolved.

View File

@@ -0,0 +1,27 @@
# Grain Analysis
Label connected grain regions in a binary mask and compute per-grain statistics: area, equivalent diameter, mean/max height, bounding box. Equivalent to Gwyddion's grain statistics tools.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Height field providing z values for per-grain statistics |
| mask | IMAGE | Yes | Binary mask defining grain regions (white = grain) |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| grain_stats | DATA_TABLE | Per-grain table with area, equivalent diameter, mean/max height, bounding box, and centroid |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| min_size | INT | 10 | Minimum grain area in pixels; smaller connected regions are ignored (1100000) |
## Limitations
- Grain detection uses 2D connected-component labeling on the binary mask; the field and mask must have the same pixel dimensions.
- Physical area and diameter values require the field to carry valid physical calibration (xreal, yreal, si_unit_xy).

View File

@@ -0,0 +1,29 @@
# Grain Distance Transform
Compute the mask distance transform using Gwyddion-style interior, exterior, or signed output. Supports Euclidean, city-block, chessboard, and octagonal distance variants, with optional image-boundary handling matching mask_edt.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Field providing physical calibration for the output |
| mask | IMAGE | Yes | Binary mask to compute distances for |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| distance | DATA_FIELD | Distance transform field in physical units |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| distance_type | dropdown | euclidean | Distance metric: euclidean, cityblock, chess (Chebyshev), octagonal48, octagonal84, or octagonal |
| output_type | dropdown | interior | Output mode: interior (distances inside grains), exterior (distances outside), or signed (positive inside, negative outside) |
| from_border | BOOLEAN | True | When enabled, image borders are treated as mask boundaries |
## Limitations
- Output distances are in physical xy units derived from the field calibration.
- The mask must have the same pixel dimensions as the field.

View File

@@ -0,0 +1,28 @@
# Grain Filter
Remove grains from a binary mask based on size and border contact. Equivalent to Gwyddion's grain_filter module (grain_filter.c).
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| mask | IMAGE | Yes | Binary mask containing grain regions to filter |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| filtered_mask | IMAGE | Binary mask with unwanted grains removed |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| min_area | INT | 10 | Discard grains with fewer pixels than this value (0 = no lower limit) |
| max_area | INT | 0 | Discard grains with more pixels than this value (0 = no upper limit) |
| remove_border | BOOLEAN | False | Discard any grain that touches the image edge |
## Limitations
- Grain detection uses 4-connected or 8-connected labeling; the exact connectivity is determined by the implementation.
- min_area and max_area are in pixels, not physical units.

28
docs/nodes/Histogram.md Normal file
View File

@@ -0,0 +1,28 @@
# Histogram
Compute the height distribution histogram (DH). Use log scale to reveal small peaks next to a dominant background. Outputs marker measurements while showing the histogram interactively in-node. Equivalent to gwy_data_field_dh.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Input field |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| measurements | RECORD_TABLE | Measurements at the two cursor markers (x/y positions and dx/dy) |
| marker_pair | COORDPAIR | Current cursor marker positions |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| n_bins | INT | 256 | Number of histogram bins (101000) |
| y_scale | dropdown | linear | Y-axis scale: linear or log |
## Limitations
- Cursor positions are stored as fractions of the histogram range and are set interactively.
- Log scale displays bins as log(count); bins with zero count appear as the minimum log value.

View File

@@ -0,0 +1,25 @@
# Image (Demo)
Load a bundled demo file so you can try the application without providing your own data. The file list is populated from the built-in demo directory at startup.
## Inputs
None.
## Outputs
| Name | Type | Description |
|------|------|-------------|
| field | DATA_FIELD | Loaded demo field |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| name | dropdown | (first demo file) | Name of the bundled demo file to load |
| colormap | dropdown | viridis | Colormap applied to the field; hidden when colormap_map is connected |
## Limitations
- Only files present in the bundled demo directory are available; custom files cannot be added here.
- If no demo files are found, the dropdown shows "(no demo files found)".

28
docs/nodes/Image.md Normal file
View File

@@ -0,0 +1,28 @@
# Image
Load any supported file. SPM formats (.gwy, .sxm, .ibw) and HDF5 (.h5, .hdf5) provide calibrated dimensions; each channel gets its own output. Images (.png, .tiff, .jpg) and arrays (.npy, .npz) are loaded as uncalibrated fields.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| path | FILE_PATH | No | File path input from a Folder node or other path source; overrides the filename widget |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| path | FILE_PATH | Resolved absolute file path |
| field | DATA_FIELD | Loaded data field (one per channel for multi-channel formats) |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| filename | FILE_PICKER | "" | Path to the file to load; hidden when path input is connected |
| colormap | dropdown | viridis | Colormap applied to the loaded field; hidden when colormap_map is connected |
## Limitations
- Uncalibrated formats (images, arrays) emit a warning and produce fields without physical dimensions.
- Multi-channel files (e.g. .gwy with multiple data channels) produce one DATA_FIELD output socket per channel; the socket count is determined at load time.

View File

@@ -0,0 +1,28 @@
# Inverse 2D FFT
Reconstruct a spatial-domain image from a 2D frequency spectrum. For exact reconstruction, connect magnitude/phase (or log magnitude/phase, or PSDF/phase) from the 2D FFT node. If phase is omitted, zero phase is assumed.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| spectrum | DATA_FIELD | Yes | Frequency-domain field (output of FFT 2D) |
| phase | DATA_FIELD | No | Phase field; if omitted, zero phase is used |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| image | DATA_FIELD | Reconstructed spatial-domain field |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| representation | dropdown | magnitude | How to interpret the spectrum input: magnitude, log_magnitude, or psdf |
## Limitations
- The spectrum input must be a frequency-domain DATA_FIELD; connecting a spatial-domain field raises an error.
- If phase is connected, it must also be a frequency-domain field with the same shape as the spectrum.
- Reconstruction from PSDF (which discards phase) assumes zero phase and produces a symmetric result.

View File

@@ -0,0 +1,26 @@
# Kuwahara Filter
Edge-preserving smoothing using Kuwahara's minimum-variance quadrant method. Unlike Gaussian blur, sharp boundaries are preserved. Equivalent to Gwyddion's Kuwahara filter.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Input field to filter |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| filtered | DATA_FIELD | Smoothed field with preserved edges |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| iterations | INT | 1 | Number of times the 5×5 Kuwahara pass is applied (120) |
## Limitations
- The kernel is fixed at 5×5 pixels; coarser smoothing requires more iterations.
- Multiple iterations increase processing time proportionally; 20 iterations on a large field may be slow.

View File

@@ -0,0 +1,33 @@
# Line Correction
Correct scan-line mismatches using Gwyddion-derived row alignment methods. Supports median and trimmed row alignment, difference-based alignment, polynomial row leveling, and step-line correction from Gwyddion's linecorrect/linematch modules.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Input field with scan-line artifacts |
| mask | IMAGE | No | Binary mask to include or exclude regions during correction |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| corrected | DATA_FIELD | Field with scan-line offsets removed |
| background | DATA_FIELD | Estimated per-line background that was subtracted |
| row_shifts | LINE | Per-row shift values applied during correction |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| method | dropdown | median | Alignment method: median, median_diff, trimmed_mean, trimmed_diff, polynomial, or step |
| direction | dropdown | horizontal | Direction of scan lines to correct: horizontal or vertical |
| masking | dropdown | ignore | How to use the mask: ignore, include (correct using masked rows only), or exclude |
| trim_fraction | FLOAT | 0.05 | Fraction of extreme values to trim; visible only for trimmed_mean and trimmed_diff methods (00.5) |
| polynomial_degree | INT | 1 | Polynomial degree for the polynomial method (05); visible only for polynomial method |
## Limitations
- The step method is designed for step-like scan artifacts and may over-correct smooth surfaces.
- Mask shape must match the field shape if a mask is connected.

View File

@@ -0,0 +1,27 @@
# Local Contrast
Expand the local dynamic range at each pixel to reveal fine surface features that are hidden by global contrast range. Equivalent to Gwyddion local_contrast.c.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Input field |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| result | DATA_FIELD | Field with enhanced local contrast |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| kernel_size | INT | 10 | Size of the local neighbourhood window in pixels (2100) |
| weight | FLOAT | 0.5 | Blend weight between original and full-contrast output (0 = original, 1 = full local contrast; 01) |
## Limitations
- Large kernel sizes are slow; values above ~50 pixels may be noticeably slow on large fields.
- The enhancement is purely a display-contrast operation; it changes the underlying data values.

29
docs/nodes/Markup.md Normal file
View File

@@ -0,0 +1,29 @@
# Markup
Draw simple vector shapes (lines, rectangles, circles, arrows) over a DATA_FIELD or IMAGE without flattening the raw data. Shapes are drawn interactively in the preview panel.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| input | ANNOTATION_SOURCE (DATA_FIELD or IMAGE) | Yes | Background image or field to annotate |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| output | ANNOTATION_SOURCE | Input with vector markup overlay attached |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| shape | dropdown | arrow | Shape type to draw next: line, rectangle, circle, or arrow |
| stroke_color | STRING (color picker) | #ff0000 | Color for newly drawn shapes |
| stroke_width | INT | 3 | Line thickness in display pixels for newly drawn shapes (164) |
| clear_shapes | BUTTON | — | Remove all drawn shapes |
## Limitations
- Shapes are stored as fractional coordinates; physical positions depend on field calibration.
- Individual shape properties (color, width) cannot be changed after drawing; use Clear Shapes to start over.

24
docs/nodes/Mask Invert.md Normal file
View File

@@ -0,0 +1,24 @@
# Mask Invert
Invert a binary mask — swap masked and unmasked regions.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| mask | IMAGE | Yes | Binary mask to invert |
| field | DATA_FIELD | No | Optional field for preview background display |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| mask | IMAGE | Inverted binary mask |
## Controls
None.
## Limitations
- None.

View File

@@ -0,0 +1,28 @@
# Mask Morphology
Apply morphological operations to a binary mask. Dilate expands regions, erode shrinks them, open (erode then dilate) removes small islands, and close (dilate then erode) fills small holes. Equivalent to Gwyddion's mask_morph.c.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| mask | IMAGE | Yes | Binary mask to process |
| field | DATA_FIELD | No | Optional field for preview background display |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| mask | IMAGE | Morphologically processed binary mask |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| operation | dropdown | dilate | Morphological operation: dilate, erode, open, or close |
| radius | INT | 1 | Structuring element radius in pixels (150) |
| shape | dropdown | disk | Structuring element shape: disk or square |
## Limitations
- Large radius values (> ~20 pixels) may be slow on large masks.

View File

@@ -0,0 +1,26 @@
# Mask Operations
Apply boolean logic to two binary masks. Supports AND, OR, XOR, NAND, NOR, XNOR, directional subtraction (A minus B, B minus A), implication, pass-through, and constant true/false outputs.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| mask_a | IMAGE | Yes | First binary mask operand |
| mask_b | IMAGE | Yes | Second binary mask operand |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| mask | IMAGE | Result of the boolean operation |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| operation | dropdown | and | Boolean operation: and, or, xor, xnor, nand, nor, a_minus_b, b_minus_a, a, b, not_a, not_b, a_implies_b, b_implies_a, false, true |
## Limitations
- Both masks must have the same pixel dimensions.

View File

@@ -0,0 +1,26 @@
# Median Filter
Apply a median filter to a DATA_FIELD. Equivalent to gwy_data_field_filter_median.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Input field to filter |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| filtered | DATA_FIELD | Median-filtered field |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| size | INT | 3 | Kernel size (side length) in pixels; odd values only (121) |
## Limitations
- The median filter is applied with a square kernel; non-square (e.g. rectangular) kernels are not supported.
- Large kernel sizes are significantly slower than the Gaussian filter for the same smoothing extent.

26
docs/nodes/Note.md Normal file
View File

@@ -0,0 +1,26 @@
# Note
Read the Note metadata from an .ibw (Igor binary wave) file and display all entries as a table of key/value pairs.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| path | FILE_PATH | No | File path from a Folder or other path node; overrides the filename widget |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| note | DATA_TABLE | Key/value table of all metadata entries from the IBW note |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| filename | FILE_PICKER | "" | Path to the .ibw file; hidden when path input is connected |
## Limitations
- Only .ibw files are supported; other formats raise an error.
- If the .ibw note section is empty or missing, an error is raised.

23
docs/nodes/Number.md Normal file
View File

@@ -0,0 +1,23 @@
# Number
Output a fixed numeric value. When connected to FLOAT inputs the exact value is used; INT inputs round to the nearest integer at execution time.
## Inputs
None.
## Outputs
| Name | Type | Description |
|------|------|-------------|
| value | FLOAT | The numeric value set by the widget |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| value | FLOAT | 0.0 | The numeric value to output |
## Limitations
- None.

27
docs/nodes/PSDF.md Normal file
View File

@@ -0,0 +1,27 @@
# PSDF
Compute the two-dimensional power spectral density function with Gwyddion-style window RMS compensation and centered zero frequency. Equivalent to psdf2d / gwy_data_field_2dpsdf.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Input spatial-domain field |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| psdf | DATA_FIELD | 2D power spectral density, centered on DC |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| windowing | dropdown | hann | Window function applied before FFT to reduce spectral leakage: hann, hamming, blackman, or none |
| level | dropdown | mean | Pre-processing: subtract mean, subtract plane, or none |
## Limitations
- Output is in the frequency domain; physical units on axes are spatial frequency (1/m) and PSDF units are z_unit²·m².
- Window RMS compensation is applied to normalize the spectral density consistently across window choices.

26
docs/nodes/Plane Level.md Normal file
View File

@@ -0,0 +1,26 @@
# Plane Level
Fit and subtract a least-squares plane from the data. Supports include/exclude mask fitting for flattening around features, similar to masked plane fitting workflows in Gwyddion.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Input field to level |
| mask | IMAGE | No | Binary mask for selecting which pixels to include in the plane fit |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| leveled | DATA_FIELD | Field with the fitted plane subtracted |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| masking | dropdown | ignore | How to use the mask: ignore (use all pixels), include (fit plane to masked pixels only), or exclude (exclude masked pixels from fit) |
## Limitations
- When masking is include or exclude, the unmasked/masked region must contain at least three non-collinear pixels to fit a plane.

View File

@@ -0,0 +1,28 @@
# Polynomial Level
Fit and subtract a polynomial background of given degree in x and y. Equivalent to gwy_data_field_fit_polynom.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Input field to level |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| leveled | DATA_FIELD | Field with polynomial background subtracted |
| background | DATA_FIELD | The fitted polynomial background surface |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| degree_x | INT | 2 | Polynomial degree in the x direction (05) |
| degree_y | INT | 2 | Polynomial degree in the y direction (05) |
## Limitations
- High polynomial degrees (> 4) may overfit and introduce artificial long-range modulation.
- No masking support; all pixels contribute equally to the fit.

25
docs/nodes/Preview.md Normal file
View File

@@ -0,0 +1,25 @@
# Preview
Display an IMAGE or DATA_FIELD as a coloured thumbnail in the node panel.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| input | ANNOTATION_SOURCE (DATA_FIELD or IMAGE) | No | Field or image to display |
| colormap_map | COLORMAP | No | Colormap socket; overrides the colormap widget |
## Outputs
None.
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| colormap | dropdown | auto | Colormap used when rendering a DATA_FIELD or grayscale IMAGE; hidden when colormap_map is connected |
## Limitations
- When no input is connected, an error is raised at execution time.
- Connecting a FILE_PATH socket (instead of DATA_FIELD) raises a type error; ensure the correct socket is connected.

21
docs/nodes/Print Table.md Normal file
View File

@@ -0,0 +1,21 @@
# Print Table
Send a measurement or record table to the browser as a WebSocket message for display.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| table | RECORD_TABLE or DATA_TABLE | Yes | Table to display |
## Outputs
None.
## Controls
None.
## Limitations
- None.

View File

@@ -0,0 +1,28 @@
# Radial Profile
Compute the azimuthally averaged radial profile from a centre point. The output x-axis is radius in physical xy units. Equivalent to gwy_data_field_angular_average used by Gwyddion's Radial Profile tool.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Input field |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| profile | LINE | Radially averaged profile vs. radius |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| cx | FLOAT | 0.5 | Centre x position as a fraction of field width (0 = left, 1 = right) |
| cy | FLOAT | 0.5 | Centre y position as a fraction of field height (0 = top, 1 = bottom) |
| n_bins | INT | 128 | Number of radial bins (44096) |
## Limitations
- Pixels are assigned to radial bins by Euclidean distance; bins near the centre contain fewer pixels and may be noisier.
- Physical x-axis units come from the field's si_unit_xy; uncalibrated fields produce pixel-unit radii.

28
docs/nodes/Resample.md Normal file
View File

@@ -0,0 +1,28 @@
# Resample
Resample a DATA_FIELD to a new pixel resolution while preserving physical dimensions. Physical size (xreal, yreal) is unchanged; pixel size dx/dy scales accordingly. Equivalent to gwy_data_field_new_resampled.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Input field to resample |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| resampled | DATA_FIELD | Resampled field at the new resolution |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| width | INT | 256 | Output pixel width (216384) |
| height | INT | 256 | Output pixel height (216384) |
| interpolation | dropdown | linear | Interpolation method: linear, cubic, or nearest |
## Limitations
- Physical dimensions are preserved; upsampling does not add new information.
- Very large output sizes (e.g. 16384×16384) require substantial memory.

28
docs/nodes/Rotate.md Normal file
View File

@@ -0,0 +1,28 @@
# Rotate
Rotate a DATA_FIELD counterclockwise by an angle in degrees. Optionally expand the canvas to keep the full rotated field while preserving the field center.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Input field to rotate |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| field | DATA_FIELD | Rotated field |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| angle | FLOAT | 90.0 | Rotation angle in degrees, counterclockwise (360 to 360) |
| interpolation | dropdown | bilinear | Interpolation method for resampling: bilinear, nearest, or bicubic |
| expand_canvas | BOOLEAN | True | When True, canvas is expanded to contain the full rotated image; when False, canvas is clipped to original size |
## Limitations
- Rotation by angles other than multiples of 90° introduces interpolation artefacts.
- expand_canvas may produce fields with non-square pixel sizes for arbitrary angles.

29
docs/nodes/Save Layers.md Normal file
View File

@@ -0,0 +1,29 @@
# Save Layers
Save one or more image/field layers to a single file. Each layer input accepts either a DATA_FIELD or an IMAGE, including annotated images. Use this for composing multi-channel stacks. Does not auto-run; click Save to write.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| directory | DIRECTORY | No | Optional directory path from a Folder node; overrides the directory_path widget |
| field_0 … field_N | DATA_FIELD, IMAGE, or ANNOTATION_SOURCE | No | Layer inputs; a new slot appears as each one is filled |
## Outputs
None.
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| filename | STRING | "" | Output filename (without directory); used together with directory_path |
| directory_path | FOLDER_PICKER | "" | Output directory; hidden when directory input is connected |
| format | dropdown | TIFF | Output format: TIFF (multi-page, float32 for fields) or NPZ (named arrays) |
| layer_name_0 … layer_name_N | STRING | "" | Optional name for each layer; used as TIFF page descriptions or NPZ array keys |
## Limitations
- At least one layer must be connected; an error is raised otherwise.
- TIFF writes DATA_FIELD layers as float32; IMAGE layers are written as uint8.
- NPZ keys are sanitized to valid Python identifiers; duplicate names are made unique with numeric suffixes.

28
docs/nodes/Save.md Normal file
View File

@@ -0,0 +1,28 @@
# Save
Save a single value to disk. Supports fields, images, lines, tables, scalars, and 3D meshes. Does not auto-run; click Save to write.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| value | DATA_FIELD, IMAGE, ANNOTATION_SOURCE, LINE, RECORD_TABLE, DATA_TABLE, MESH_MODEL, or FLOAT | Yes | Value to save |
| directory | DIRECTORY | No | Optional directory path from a Folder node; overrides the directory_path widget |
## Outputs
None.
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| filename | STRING | "" | Output filename |
| directory_path | FOLDER_PICKER | "" | Output directory; hidden when directory input is connected |
| format | STRING (context-dependent) | TIFF | Output format; available choices depend on the connected input type |
| plot_title | STRING | "" | Optional title for line plots saved as PNG or TIFF |
## Limitations
- Available formats per input type: DATA_FIELD → TIFF, PNG, NPZ; IMAGE → PNG, TIFF, NPZ; LINE → PNG, TIFF, CSV, NPZ, JSON; RECORD_TABLE/DATA_TABLE → CSV, JSON; FLOAT → TXT, JSON; MESH_MODEL → OBJ, STL.
- divide-by-zero or NaN values in fields are preserved in TIFF/NPZ but may not render correctly in PNG.

View File

@@ -0,0 +1,31 @@
# Scar Removal
Detect and remove horizontal scan scars using Gwyddion-derived scar marking thresholds, then interpolate over the detected mask with a Laplace-style inpaint.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Input field with scan scars |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| corrected | DATA_FIELD | Field with scars removed and interpolated |
| scar_mask | IMAGE | Binary mask of the detected scar pixels |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| scar_type | dropdown | both | Which scar polarity to detect: both, positive (bright), or negative (dark) |
| threshold_high | FLOAT | 0.666 | High threshold relative to local RMS for strong scar detection (02) |
| threshold_low | FLOAT | 0.25 | Low threshold for extending already-detected scars (02) |
| min_length | INT | 16 | Minimum horizontal run length in pixels to classify as a scar (14096) |
| max_width | INT | 4 | Maximum vertical width in pixels for a scar candidate (132) |
## Limitations
- Designed for horizontal (fast-scan) scars only; vertical scars are not detected.
- Aggressive thresholds may remove legitimate surface features that resemble scars.

View File

@@ -0,0 +1,27 @@
# Slope Distribution
Compute the angular slope distribution of a DATA_FIELD surface. Equivalent to Gwyddion's slope_dist module (slope_dist.c).
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Input surface field |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| distribution | LINE | Slope distribution histogram |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| distribution | dropdown | theta | Distribution type: theta (inclination angle, probability density in 1/deg), phi (azimuthal direction, weighted by slope², 0360°), or gradient (slope magnitude, probability density in 1/(z/xy)) |
| n_bins | INT | 90 | Number of histogram bins (101000) |
## Limitations
- The gradient magnitude distribution requires valid physical xy and z units for correct normalization.
- phi distribution is weighted by slope squared; flat surfaces with near-zero slopes produce a noisy azimuthal distribution.

View File

@@ -0,0 +1,28 @@
# Spot Removal
Fill defect pixels (hot pixels, dropouts, scan artifacts) by interpolation. The mask defines defect locations. Equivalent to Gwyddion spotremove.c.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Input field with defect pixels |
| mask | IMAGE | No | Binary mask marking defect pixel locations; if omitted, no inpainting is performed |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| result | DATA_FIELD | Field with defect pixels replaced by interpolated values |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| method | dropdown | laplace | Inpainting method: laplace (smooth Laplace equation solution), mean (local mean), or zero |
| max_iter | INT | 100 | Maximum number of iterations for the Laplace solver (12000) |
## Limitations
- Large masked regions may not converge fully within max_iter iterations using the Laplace method.
- The mean method uses a simple neighbourhood average and may leave visible discontinuities at large defect clusters.

23
docs/nodes/Statistics.md Normal file
View File

@@ -0,0 +1,23 @@
# Statistics
Compute basic surface statistics: min, max, mean, RMS roughness, median, and skewness. Equivalent to gwy_data_field_get_min/max/avg/rms.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Input field to analyze |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| stats | RECORD_TABLE | Table of statistical quantities with values and units |
## Controls
None.
## Limitations
- None.

27
docs/nodes/Stats.md Normal file
View File

@@ -0,0 +1,27 @@
# Stats
Compute a contextual scalar statistic from a LINE, record table, DATA_FIELD, or IMAGE. The available operations adapt to the connected input type.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| input | DATA_FIELD, IMAGE, LINE, or DATA_TABLE | Yes | Input to compute statistics on |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| value | FLOAT | Computed scalar statistic |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| operation | STRING (context-dependent dropdown) | mean | Statistical operation; available choices depend on the input type |
| column | STRING | value | Column name for DATA_TABLE inputs; visible only when a DATA_TABLE is connected |
## Limitations
- Available operations vary by input type; connecting a different type changes the available options.
- For DATA_TABLE inputs, the column must match an existing column name; an error is raised otherwise.

View File

@@ -0,0 +1,28 @@
# Template Match
Find a template pattern within a larger data field using normalised cross-correlation. The score output shows match quality (1 = perfect match). Equivalent to Gwyddion maskcor.c.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| image | DATA_FIELD | Yes | Larger field to search in |
| template | DATA_FIELD | Yes | Smaller template pattern to find |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| score | DATA_FIELD | Normalized cross-correlation score map |
| detections | IMAGE | Binary mask marking positions above the threshold |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| threshold | FLOAT | 0.8 | Minimum correlation score to mark as a detection (0.01.0) |
## Limitations
- The template must be smaller than the image; equal or larger sizes are not supported.
- Normalized cross-correlation assumes uniform background; strong global gradients reduce detection accuracy.

22
docs/nodes/Text Note.md Normal file
View File

@@ -0,0 +1,22 @@
# Text Note
A floating text card for annotating workflows. Supports Markdown formatting. Does not process data and has no outputs.
## Inputs
None.
## Outputs
None.
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| text | STRING (multiline) | "# Guide\n\nDouble-click to edit this note.\n\n- Step 1\n- Step 2" | Markdown text displayed on the canvas card |
| color | dropdown | default | Card background color: default, blue, green, yellow, red, or purple |
## Limitations
- None.

View File

@@ -0,0 +1,29 @@
# Threshold Mask
Create a binary mask by thresholding data. Otsu automatically finds the optimal threshold. Equivalent to Gwyddion's threshold and otsu_threshold modules.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Input field to threshold |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| mask | IMAGE | Binary mask (white = selected pixels) |
| threshold | RECORD_TABLE | Table with the threshold value applied |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| method | dropdown | absolute | Thresholding method: absolute (raw data value), relative (fraction of minmax range), or otsu (automatic Otsu threshold) |
| threshold | FLOAT | 0.0 | Threshold value; for absolute: raw z value; for relative: fraction 01; ignored for otsu (socket-only input) |
| direction | dropdown | above | Which pixels to select: above or below the threshold |
## Limitations
- For the relative method, the threshold fraction is applied to the full data range [min, max].
- Otsu thresholding may not give meaningful results on non-bimodal height distributions.

View File

@@ -0,0 +1,26 @@
# Tip Deconvolution
Reconstruct the true surface from a tip-broadened measured AFM image. Uses morphological grey erosion (Villarrubia algorithm). Equivalent to gwy_tip_erosion (tip.c).
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Measured AFM image |
| tip | DATA_FIELD | Yes | Tip shape field, e.g. from Tip Model or Blind Tip Estimate |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| surface | DATA_FIELD | Reconstructed true surface |
## Controls
None.
## Limitations
- The tip pixel size must match the image pixel size exactly; mismatched calibrations will produce incorrect results.
- Deconvolution can only reduce tip broadening; it cannot recover information lost below the noise floor.
- Very large tip sizes are slow due to the nested loop over all tip pixels.

30
docs/nodes/Tip Model.md Normal file
View File

@@ -0,0 +1,30 @@
# Tip Model
Generate a synthetic AFM tip model DATA_FIELD. The input field sets the pixel size for the tip. The apex (centre pixel) is the maximum value; edges are shifted to zero. Equivalent to gwy_tip_model_preset_create (tip.c / tip_model.c).
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Reference field that sets the tip pixel size |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| tip | DATA_FIELD | Synthetic tip shape field |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| shape | dropdown | parabola | Tip geometry: parabola (paraboloid with apex radius R), cone (sphere-capped cone), or sphere (ball-on-stick) |
| radius | FLOAT | 10 nm | Apex radius of curvature in metres (1e-10 to 1e-6) |
| half_angle | FLOAT | 20.0 | Half-cone angle from the tip axis in degrees for the cone shape (189°) |
| n_pixels | INT | 65 | Side length of the square tip grid in pixels (odd values only, 3511) |
## Limitations
- half_angle is only used for the cone shape.
- The tip grid must be smaller than or equal to the image size for Tip Deconvolution to work correctly.
- Large n_pixels values produce large tip grids that make deconvolution slow.

View File

@@ -0,0 +1,27 @@
# Value Display
Display a FLOAT value, or a selected numeric row from a measurement table, and pass the value through unchanged.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| value | FLOAT or RECORD_TABLE | No | Numeric value or measurement table to display; overrides the text input when connected |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| value | FLOAT | The numeric value (from socket or parsed from text) |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| number_input | STRING (text input) | "0" | Manual numeric entry, e.g. "1.5 nm"; hidden when value socket is connected |
| measurement | STRING (dropdown) | "" | Row selector when a RECORD_TABLE is connected; visible only for RECORD_TABLE inputs |
## Limitations
- When a RECORD_TABLE is connected, only rows with numeric values can be selected; non-numeric rows are not accessible.
- Manual text entry supports optional SI unit suffix (e.g. "1.5 nm") for display only; the output FLOAT is always the raw numeric value.

View File

@@ -0,0 +1,33 @@
# Watershed Segmentation
Segment a height field into grains using the two-stage Gwyddion watershed workflow: drop-based seed location followed by watershed growth. Supports hill or valley detection and optional union/intersection with an existing mask.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Input topographic field |
| mask | IMAGE | No | Optional existing mask to combine with the watershed result |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| mask | IMAGE | Binary grain mask from watershed segmentation |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| invert_height | BOOLEAN | False | When True, detects valleys instead of hills (inverts the height field) |
| locate_steps | INT | 10 | Number of drop steps in the seed location stage (1200) |
| locate_threshold | INT | 10 | Minimum drop threshold for seed acceptance (0100000) |
| locate_drop_size | FLOAT | 0.1 | Relative drop size for seed location stage (0.00011.0) |
| watershed_steps | INT | 20 | Number of steps in the watershed growth stage (12000) |
| watershed_drop_size | FLOAT | 0.1 | Relative drop size for watershed growth stage (0.00011.0) |
| combine_mode | dropdown | replace | How to combine with an existing mask: replace (ignore existing), union (OR), or intersection (AND) |
## Limitations
- Parameter tuning is required; the default settings work best for isolated round features.
- Very large locate_threshold values may reject all seeds and produce an empty mask.

View File

@@ -0,0 +1,29 @@
# Wavelet Denoise
Denoise a DATA_FIELD using wavelet coefficient thresholding. BayesShrink adapts the threshold per sub-band; VisuShrink uses a global threshold. Equivalent to applying DWT from Gwyddion dwt.c with coefficient thresholding.
## Inputs
| Name | Type | Required | Description |
|------|------|----------|-------------|
| field | DATA_FIELD | Yes | Input field to denoise |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| denoised | DATA_FIELD | Denoised field |
## Controls
| Name | Type | Default | Description |
|------|------|---------|-------------|
| wavelet | dropdown | db4 | Wavelet family: db1 (Haar), db2, db4, db8, sym4, coif1, or bior1.3 |
| method | dropdown | BayesShrink | Threshold estimation method: BayesShrink (per sub-band adaptive) or VisuShrink (global universal) |
| sigma | FLOAT | 0.0 | Noise level estimate in data units; 0 = automatic estimation (01.0) |
| mode | dropdown | soft | Thresholding mode: soft (smooth shrinkage) or hard (zero below threshold) |
## Limitations
- The field size should ideally be a power of two for best wavelet decomposition; other sizes are handled by padding.
- sigma = 0 triggers automatic noise estimation from the finest-scale wavelet coefficients; this may be inaccurate on strongly structured surfaces.

View File

@@ -1,7 +1,12 @@
import React, { useContext, useRef, useCallback, useState, useEffect, memo, lazy, Suspense } from 'react';
import ReactDOM from 'react-dom';
import { Handle, NodeResizeControl, Position, useStore } from '@xyflow/react';
import { marked } from 'marked';
import { getNodeDoc } from './api';
import LinePlotOverlay from './LinePlotOverlay';
marked.use({ breaks: true, gfm: true });
const SurfaceView = lazy(() => import('./SurfaceView'));
const CrossSectionOverlay = lazy(() => import('./CrossSectionOverlay'));
const CropBoxOverlay = lazy(() => import('./CropBoxOverlay'));
@@ -973,10 +978,48 @@ function NodeTable({ rows }) {
);
}
// ── Node help panel (portal) ──────────────────────────────────────────
function NodeHelpPanel({ title, content, onClose }) {
useEffect(() => {
const handler = (e) => { if (e.key === 'Escape') onClose(); };
document.addEventListener('keydown', handler);
return () => document.removeEventListener('keydown', handler);
}, [onClose]);
return ReactDOM.createPortal(
<div className="node-help-panel">
<div className="node-help-panel-header">
<span className="node-help-panel-title">{title}</span>
<button className="node-help-panel-close" onClick={onClose} title="Close">×</button>
</div>
<div
className="node-help-panel-body nowheel"
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html: marked.parse(content || '') }}
/>
</div>,
document.body,
);
}
// ── CustomNode component ──────────────────────────────────────────────
function CustomNode({ id, data }) {
const ctx = useContext(NodeContext);
const [helpOpen, setHelpOpen] = useState(false);
const [helpContent, setHelpContent] = useState(null);
const onHelpClick = useCallback(async (e) => {
e.stopPropagation();
if (helpOpen) { setHelpOpen(false); return; }
setHelpOpen(true);
if (helpContent === null) {
const text = await getNodeDoc(data.label);
setHelpContent(text || '*No documentation available for this node.*');
}
}, [helpOpen, helpContent, data.label]);
if (data.className === 'Group') {
return <GroupNode id={id} data={data} />;
}
@@ -1181,7 +1224,10 @@ function CustomNode({ id, data }) {
{/* Title */}
<div className="node-title drag-handle" style={{ background: catColor }}>
<span className="node-title-main">{data.label}</span>
{headerMeta && <span className="node-title-meta" title={headerMeta}>{headerMeta}</span>}
<div className="node-title-right">
{headerMeta && <span className="node-title-meta" title={headerMeta}>{headerMeta}</span>}
<button className="node-help-btn nodrag nopan" title="Documentation" onClick={onHelpClick}>?</button>
</div>
</div>
<div className="node-body">
@@ -1528,6 +1574,13 @@ function CustomNode({ id, data }) {
)}
</div>
</div>
{helpOpen && (
<NodeHelpPanel
title={data.label}
content={helpContent ?? '*Loading…*'}
onClose={() => setHelpOpen(false)}
/>
)}
</>
);
}

View File

@@ -62,6 +62,12 @@ export async function getNodes() {
return r.json();
}
export async function getNodeDoc(displayName) {
const r = await sessionFetch(`/docs?name=${encodeURIComponent(displayName)}`);
if (!r.ok) return null;
return r.text();
}
export async function getFiles() {
const r = await sessionFetch('/files');
if (!r.ok) return [];

View File

@@ -435,6 +435,149 @@ html, body, #root {
text-overflow: ellipsis;
}
.node-title-right {
display: flex;
align-items: center;
gap: 5px;
flex-shrink: 0;
}
.node-help-btn {
width: 15px;
height: 15px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.12);
border: 1px solid rgba(255, 255, 255, 0.25);
color: rgba(255, 255, 255, 0.75);
font-size: 9px;
font-weight: 700;
line-height: 1;
padding: 0;
cursor: pointer;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
transition: background 0.15s, border-color 0.15s;
}
.node-help-btn:hover {
background: rgba(255, 255, 255, 0.28);
border-color: rgba(255, 255, 255, 0.5);
}
/* ── Node help panel ─────────────────────────────────────── */
.node-help-panel {
position: fixed;
top: 60px;
right: 20px;
width: 420px;
max-height: calc(100vh - 80px);
background: #1e293b;
border: 1px solid #334155;
border-radius: 8px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.55);
display: flex;
flex-direction: column;
z-index: 9999;
overflow: hidden;
}
.node-help-panel-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 9px 12px;
border-bottom: 1px solid #334155;
background: #0f172a;
flex-shrink: 0;
}
.node-help-panel-title {
font-weight: 600;
font-size: 13px;
color: #f1f5f9;
}
.node-help-panel-close {
background: none;
border: none;
color: #64748b;
font-size: 20px;
line-height: 1;
padding: 0 2px;
cursor: pointer;
transition: color 0.12s;
}
.node-help-panel-close:hover {
color: #f1f5f9;
}
.node-help-panel-body {
padding: 14px 16px;
overflow-y: auto;
flex: 1;
font-size: 12.5px;
color: #cbd5e1;
line-height: 1.65;
}
.node-help-panel-body h1,
.node-help-panel-body h2,
.node-help-panel-body h3 {
color: #f1f5f9;
margin: 14px 0 5px;
font-weight: 600;
}
.node-help-panel-body h1 { font-size: 15px; margin-top: 0; }
.node-help-panel-body h2 { font-size: 13px; }
.node-help-panel-body h3 { font-size: 12px; }
.node-help-panel-body p { margin: 4px 0 8px; }
.node-help-panel-body table {
border-collapse: collapse;
width: 100%;
font-size: 11.5px;
margin: 8px 0 12px;
}
.node-help-panel-body th,
.node-help-panel-body td {
border: 1px solid #334155;
padding: 4px 8px;
text-align: left;
}
.node-help-panel-body th {
background: #0f172a;
color: #94a3b8;
font-weight: 600;
}
.node-help-panel-body code {
background: #0f172a;
padding: 1px 5px;
border-radius: 3px;
font-size: 11px;
color: #7dd3fc;
}
.node-help-panel-body ul,
.node-help-panel-body ol {
padding-left: 18px;
margin: 4px 0 8px;
}
.node-help-panel-body li { margin: 2px 0; }
.node-help-panel-body em { color: #94a3b8; }
.node-help-panel-body strong { color: #e2e8f0; }
.node-body {
padding: 4px 0;
display: flex;