Repository navigation
G1: declare axes as a family; delete the component enums - #1170
Merged
Merged
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The kernel's axes are nominal Axis classes registered in an AxisFamily, with roles (PartitionAxis, StackAxis, ColourAxis, TileAxis, TimeAxis, DefaultVariable, DefaultGroupBy) as capability mixins checked for cardinality and value kinds (LabelValued, OrdinalValued). The microscopy family is declared in openhcs/domains/microscopy/axes.py and activated by the product entry point. Deleted: AllComponents, VariableComponents, SequentialComponents, StreamingComponents, GroupBy, _ComponentTemplate, ComponentConfiguration and its factory, get_openhcs_config and the per-call enum construction, the GroupBy equality patch, convert_enum_by_value, the DEFAULT_*/MULTIPROCESSING_AXIS import-time copies and every .value identity bridge. Consumers take axis classes; GroupBy.NONE is Ungrouped; subsets are family queries; strings exist only at boundaries via Axis.name. Kernel member references became role queries: role-keyed strategies for source metadata projection, Zarr NGFF axes and viewer labels; viewer display configs carry one mode field per role; plane filenames derive from declared axis tokens; function requirements declare roles (required_axis_roles, allowed_group_by_roles). Durable state: tools/cutover/g1_axis_family.py rewrites pre-G1 config documents and pickled pipelines (owner decision G1-Q1). Guards: tests/unit/test_axis_family_guards.py. Witness: tests/unit/test_axis_family_witness.py (a remote-sensing family). Lockstep: python-introspect#17 (AnnotationChoices), PyQT-reactive#16. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Resolutions keep all three intents: the C3 editor derives its columns from the dataclass (ComponentSelector.component declares AxisChoices, which the choice cell editor renders by axis name); C5/L1 provider families and metaclass_registry strategies/caches; G1 axis classes with no component enums. Axis and family declarations are now validated after class creation: raising from __init_subclass__ left a half-built ABC subclass that made unrelated axes pass role checks (witness regression assertion added). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Pickled pipelines are deprecated; the pickle branch is deleted. The tool now rewrites any pycodify-generated source (.py pipelines, config documents, custom functions): enum members, GroupBy.NONE, per-member viewer mode fields, required_variable_components/allowed_group_by and their imports, keeping a .pre-g1 backup. A test converts fixtures rendered by pre-G1 main and loads and validates them on G1. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Axis declarations register their JSON encoding with python_introspect's to_jsonable (openhcs/serialization/json.py moved there in L2). Submodules point at python-introspect 0.2.3 (AnnotationChoices) and pyqt-reactive 0.3.28; pins raised to match. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- RuntimeArtifactAddress.from_dict decodes axis names through the active family (live measurement previews failed with "'channel' is not an axis"). - Pattern matching rejects non-axis variable components instead of silently matching nothing. - Axis declarations register under their boundary name, so python-introspect's to_jsonable spells them by name with no extra registration; form choice sets move to openhcs.core.axis_boundaries so importing openhcs (and openhcs.desktop_deployment) no longer loads python_introspect. - Stale tests updated to axis classes; the MCP contract fixture is regenerated for the per-role viewer mode fields. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Surface G1 (receipt:
docs/refactor/consolidation-20261009/G1-axis-family.md).What changed
openhcs/core/axes.py: nominalAxisclasses registered in anAxisFamily(AutoRegisterMeta). Roles are capability mixins with cardinality checked when a family is declared:PartitionAxis(exactly one),StackAxis(at most one),ColourAxis,TileAxis,TimeAxis,DefaultVariable,DefaultGroupBy(at most one). Value kinds areLabelValuedandOrdinalValued.Ungroupedis the explicit absent-grouping declaration. A role-keyed strategy mixin replaces the strategies that were keyed by enum member.openhcs/domains/microscopy/axes.py. The product entry point (openhcs/__init__.py) activates it once per process. No kernel module imports the domain._ComponentTemplate,ComponentConfigurationand its factory, the per-callget_openhcs_config, the GroupBy__eq__/__hash__patch,convert_enum_by_value,ComponentSet.coerce*, the import-timeDEFAULT_*/MULTIPROCESSING_AXIS,OpenHCSPlaneAddress.from_values, and every.valueidentity bridge.partition_mode,tile_mode,colour_mode,stack_mode,time_mode);required_axis_roles,allowed_group_by_roles).Axis.name, andgroup_byuses"none"forUngrouped;Microscopy.Channel(new pycodify formatter);AnnotationChoices.AnnotationChoices,type[X]validation) and Render AnnotationChoices fields; provider-owned grouping labels PyQT-reactive#16 (choice widgets; the provider now owns grouping labels instead ofget_groupby_enum).Durable state (owner decision G1-Q1)
Pickled pipelines are deprecated and not converted (F1 deletes the GUI pickle path).
tools/cutover/g1_axis_family.pyrewrites pycodify Python sources (.pypipelines, config documents, custom functions): enum members,GroupBy.NONE, per-member viewer mode fields,required_variable_components/allowed_group_byand their imports, keeping a.pre-g1backup.tests/unit/test_g1_cutover_tool.pyconverts fixtures rendered by pre-G1 main and loads and validates them on G1. Tool, test and fixtures are deleted once the owner has migrated.Verification
tests/unit/test_axis_family_guards.py, 3/3 pass. The deleted names appear nowhere inopenhcs/,tests/,benchmark/orscripts/. Kernel modules neither importopenhcs.domainsnor name the microscopy family or its members. The product entry point activates Microscopy.tests/unit/test_axis_family_witness.py, 5/5 pass. A remote-sensing family (scene, tile, band, date; no stack axis) is activated in-process with zero kernel edits. These all follow it:ProcessingConfigdefaults and validation;cp_tutorial_3d_monolayerfails, with the same.pklserialization error as the baseline on main.variable_componentsandsequential_componentsrender as checkbox groups,group_byas a combo.pyclesperanto/torchnot installed, subprocess import-root checks), or a test file that did not collect on main.MCP schema changes (fixture regenerated)
All intended consequences of the per-role viewer mode fields:
openhcs_stream_plate_files_to_viewer: the Napari display-config propertiessite_mode,channel_mode,z_index_mode,timepoint_mode,well_modebecometile_mode,colour_mode,stack_mode,time_mode,partition_mode(same enum, same defaults).openhcs_set_viewer_image_color: the description now sayscolour_mode=LAYERinstead ofchannel_mode=LAYER.No other tool, surface or resource changed.
Handoff
Recorded in the receipt:
one(role)assumptions for G3/G4/G5;Production +2445/−2193. Net +252: the new kernel
axes.pyand role-keyed strategy leaves exceed the deleted factory and enum machinery. Tests +2656/−2403.G1 · PR #1170 · guards 3/3 · production −2193 +2445 · tests −2403 +2656
🤖 Generated with Claude Code