213 lines
5.1 KiB
Python
213 lines
5.1 KiB
Python
"""
|
|
Central Add Node menu manifest.
|
|
|
|
Edit MENU_LAYOUT to rearrange which nodes appear under each menu leaf and
|
|
their order within that leaf. Node classes not listed here fall back to their
|
|
class CATEGORY.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
|
|
MENU_LAYOUT: dict[str, list[str]] = {
|
|
"Input": [
|
|
"Image",
|
|
"ImageDemo",
|
|
"Folder",
|
|
"SyntheticSurface",
|
|
"Note",
|
|
"TextNote",
|
|
"Number",
|
|
"RangeSlider",
|
|
"Coordinate",
|
|
"CoordinatePair",
|
|
],
|
|
"Display": [
|
|
"PreviewImage",
|
|
"View3D",
|
|
"ColorMap",
|
|
"ColormapAdjust",
|
|
"Font",
|
|
"ValueIO",
|
|
"PrintTable",
|
|
"Save",
|
|
"Shade",
|
|
"PresentationOps",
|
|
],
|
|
"Overlay": [
|
|
"Markup",
|
|
"Annotations",
|
|
"AngleMeasure",
|
|
"Cursors",
|
|
],
|
|
"Geometry": [
|
|
"CropResizeField",
|
|
"RotateField",
|
|
"FlipField",
|
|
"Resample",
|
|
"AffineCorrection",
|
|
"PerspectiveCorrection",
|
|
"PolynomialDistortion",
|
|
"ImageStitch",
|
|
"MutualCrop",
|
|
"ImmerseDetail",
|
|
"PixelBinning",
|
|
"ExtendPad",
|
|
"FieldArithmetic",
|
|
"DisplacementField",
|
|
],
|
|
"Level & Correct": [
|
|
"FixZero",
|
|
"PlaneLevelField",
|
|
"PolyLevelField",
|
|
"FacetLevelField",
|
|
"FlattenBase",
|
|
"LineCorrection",
|
|
"DriftCorrection",
|
|
"ScarRemoval",
|
|
"SpotRemoval",
|
|
"LaplaceInterpolation",
|
|
"FractalInterpolation",
|
|
"ScanLineReorder",
|
|
"Tilt",
|
|
"WrapValue",
|
|
"DistributionCoercion",
|
|
"Calibration",
|
|
],
|
|
"Filter": [
|
|
"GaussianFilter",
|
|
"MedianFilter",
|
|
"KuwaharaFilter",
|
|
"WaveletDenoise",
|
|
"LocalContrast",
|
|
"CustomConvolution",
|
|
"Deconvolution",
|
|
"MedianBackground",
|
|
"TrimmedMean",
|
|
"RankFilter",
|
|
"Gradient",
|
|
"EdgeDetect",
|
|
],
|
|
"Spectral": [
|
|
"FFT2D",
|
|
"FFT2DInverse",
|
|
"FFTFilter",
|
|
"FFT1D",
|
|
"ACF2D",
|
|
"ACF1D",
|
|
"PSDF",
|
|
"LogPolarPSDF",
|
|
"FrequencySplit",
|
|
"CrossCorrelate",
|
|
"SuperResolution",
|
|
],
|
|
"Measure": [
|
|
"CrossSection",
|
|
"Histogram",
|
|
"Statistics",
|
|
"Stats",
|
|
"Curvature",
|
|
"ShapeFitting",
|
|
"TerraceFit",
|
|
"FractalDimension",
|
|
"Entropy",
|
|
"SlopeDistribution",
|
|
"RadialProfile",
|
|
"LatticeMeasurement",
|
|
"AngleMeasure",
|
|
"MultipleProfiles",
|
|
"StraightenPath",
|
|
"RelateFields",
|
|
"DWTAnisotropy",
|
|
],
|
|
"Detect": [
|
|
"FeatureDetection",
|
|
"HoughTransform",
|
|
"TemplateMatch",
|
|
"FacetAnalysis",
|
|
"MFMAnalysis",
|
|
"MFMCurrentSimulation",
|
|
"MFMDomainGeneration",
|
|
"ZeroCrossing",
|
|
"PFMAnalysis",
|
|
"LateralForceSim",
|
|
"SEMSimulation",
|
|
"SMMAnalysis",
|
|
"PixelClassification",
|
|
"NeuralClassification",
|
|
"LogisticClassification",
|
|
],
|
|
"Mask": [
|
|
"DrawMask",
|
|
"ThresholdMask",
|
|
"GrainMark",
|
|
"OutlierMask",
|
|
"MaskMorphology",
|
|
"MaskInvert",
|
|
"MaskOperations",
|
|
"MarkDisconnected",
|
|
"MaskShift",
|
|
"MaskNoisify",
|
|
"RectangularMask",
|
|
],
|
|
"Grains": [
|
|
"GrainDistanceTransform",
|
|
"WatershedSegmentation",
|
|
"GrainAnalysis",
|
|
"GrainFilter",
|
|
"GrainDistributions",
|
|
"GrainSummary",
|
|
"LevelGrains",
|
|
"GrainEdge",
|
|
"GrainCross",
|
|
"GrainVisualization",
|
|
],
|
|
"Tip": [
|
|
"TipModel",
|
|
"TipDeconvolution",
|
|
"BlindTipEstimate",
|
|
"TipShapeEstimate",
|
|
"PSFEstimation",
|
|
],
|
|
}
|
|
|
|
|
|
_CATEGORY_ORDER = {category: index for index, category in enumerate(MENU_LAYOUT)}
|
|
_NODE_METADATA: dict[str, dict[str, Any]] = {}
|
|
for category, class_names in MENU_LAYOUT.items():
|
|
for node_order, class_name in enumerate(class_names):
|
|
metadata = _NODE_METADATA.setdefault(class_name, {
|
|
"category": category,
|
|
"category_order": _CATEGORY_ORDER[category],
|
|
"menu_order": node_order,
|
|
"menu_categories": [],
|
|
})
|
|
metadata["menu_categories"].append({
|
|
"category": category,
|
|
"category_order": _CATEGORY_ORDER[category],
|
|
"menu_order": node_order,
|
|
})
|
|
|
|
|
|
def get_menu_metadata(class_name: str, cls: type | None = None) -> dict[str, Any]:
|
|
metadata = _NODE_METADATA.get(class_name)
|
|
if metadata is not None:
|
|
return dict(metadata)
|
|
|
|
# Nodes not listed in MENU_LAYOUT (e.g. plugins) can declare their own
|
|
# menu category via a CATEGORY class attribute. Falls back to "Unsorted".
|
|
category = getattr(cls, "CATEGORY", "Unsorted") if cls else "Unsorted"
|
|
order = len(_CATEGORY_ORDER)
|
|
return {
|
|
"category": category,
|
|
"category_order": order,
|
|
"menu_order": 10_000,
|
|
"menu_categories": [{
|
|
"category": category,
|
|
"category_order": order,
|
|
"menu_order": 10_000,
|
|
}],
|
|
}
|