Skip to content

Commit 12708ad

Browse files
committed
docs: expand paper with provenance tracking and callable support details
1 parent c51b58b commit 12708ad

File tree

1 file changed

+40
-6
lines changed

1 file changed

+40
-6
lines changed

paper.md

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ Hydra [@Yadan2019] provides hierarchical *composition* but not runtime *resoluti
7070

7171
## Beyond Dataclasses: Callable Support
7272

73-
ObjectState handles callables (functions, methods) the same way as dataclasses. When given a callable, it extracts parameters from the function signature:
73+
ObjectState handles callables (functions, methods) the same way as dataclasses. When given a callable, it extracts parameters from the function signature using Python's `inspect` module:
7474

7575
```python
7676
def gaussian_filter(image, sigma=None, preserve_range=None):
@@ -83,6 +83,28 @@ state.update_parameter("sigma", 2.0)
8383

8484
The `None` sentinel works identically for function kwargs—unset parameters inherit from the context hierarchy. This enables pipeline steps where function parameters participate in the same dual-axis inheritance as dataclass fields.
8585

86+
**Practical Impact**: In OpenHCS, users can register arbitrary Python functions (from scikit-image, CuPy, PyTorch, etc.) as pipeline steps. ObjectState automatically extracts their parameters and makes them configurable through the same hierarchical inheritance system as dataclass fields. A user can set a global default for `sigma`, override it per-pipeline, and override it again per-step—all without modifying the function itself.
87+
88+
## Provenance Tracking
89+
90+
Every parameter value is tagged with its source:
91+
92+
```python
93+
state.get_parameter_with_provenance("sigma")
94+
# Returns: (2.0, "step_config")
95+
```
96+
97+
This enables:
98+
- **UI Feedback**: Show users where a value came from (e.g., "inherited from pipeline config")
99+
- **Debugging**: Trace why a parameter has a particular value
100+
- **Dirty Tracking**: Distinguish between user-set and inherited values
101+
102+
The provenance system is the foundation for the GUI's visual feedback—empty fields show inherited values in gray, while user-set values appear in bold.
103+
104+
**Implementation Details**: Provenance is tracked via a parallel dictionary structure that mirrors the parameter structure. When a parameter is resolved through the inheritance chain, the resolution function records which scope level provided the final value. This allows the UI to display not just the value, but also its source, enabling users to understand the configuration hierarchy at a glance.
105+
106+
**Example**: A user sees `sigma = 2.0 (from pipeline config)` in the UI. They can click to see that the step config has no override, the plate config has no override, but the pipeline config sets it to 2.0. This transparency is critical for debugging configuration issues in complex pipelines.
107+
86108
## Example
87109

88110
```python
@@ -124,13 +146,25 @@ The user's mental model ("empty = inherit") maps directly to resolution semantic
124146

125147
# Research Application
126148

127-
ObjectState was developed for OpenHCS (Open High-Content Screening) to manage imaging pipeline configurations with hundreds of parameters across processing stages. The framework handles:
149+
ObjectState was developed for OpenHCS (Open High-Content Screening), an open-source platform for automated microscopy image analysis. OpenHCS pipelines process thousands of images per experiment, each requiring configuration across multiple scopes:
150+
151+
**Global Scope**: Default parameters for all plates (e.g., `num_workers=8`, `output_dir="/results"`)
152+
153+
**Plate Scope**: Per-plate overrides (e.g., `num_workers=4` for a specific plate with memory constraints)
154+
155+
**Pipeline Scope**: Per-pipeline overrides (e.g., `compression="gzip"` for Zarr output on this pipeline only)
156+
157+
**Step Scope**: Per-processing-step overrides (e.g., `sigma=2.0` for Gaussian filtering in this step)
158+
159+
Without ObjectState, each scope level would require explicit parameter passing through 20+ function calls. With ObjectState, configuration resolves automatically: a step's `sigma` parameter first checks the step config, then the pipeline config, then the plate config, then global defaults—all transparently.
160+
161+
**Interactive Parameter Tuning**: The GUI allows users to edit parameters in real-time. When a user clears a field (sets it to `None`), the UI immediately shows the inherited value via provenance tracking. When they type a value, it overrides the inheritance chain. This unifies the user's mental model ("empty = inherit") with the data model.
162+
163+
**Experiment Branching**: ObjectState's git-like undo/redo with branching timelines enables users to compare configuration strategies. A user can configure a pipeline, save it, then time-travel back and try a different configuration, creating a branching history. This is more powerful than traditional undo/redo for exploratory parameter tuning.
128164

129-
- Interactive parameter tuning with immediate feedback
130-
- Experiment branching for comparing configuration strategies
131-
- Hierarchical override patterns (step inherits from pipeline inherits from global)
165+
**Dirty Tracking**: The framework maintains both saved and live state. When a user edits a parameter, it's marked dirty. The UI shows visual feedback (flash animations) for modified fields. Users can save changes (updating the baseline) or restore to the last saved state without losing the history.
132166

133-
The zero-dependency design ensures easy integration into scientific software stacks.
167+
The zero-dependency design ensures easy integration into scientific software stacks without adding heavyweight dependencies.
134168

135169
# Acknowledgments
136170

0 commit comments

Comments
 (0)